diff --git a/.github/update.log b/.github/update.log index ebb24e5c4c..84f4df2bd2 100644 --- a/.github/update.log +++ b/.github/update.log @@ -596,3 +596,4 @@ Update On Wed Mar 20 15:20:33 CET 2024 Update On Fri Mar 22 14:55:10 CET 2024 Update On Fri Mar 22 19:26:11 CET 2024 Update On Sat Mar 23 19:27:23 CET 2024 +Update On Sun Mar 24 19:31:12 CET 2024 diff --git a/brook/brooklink.go b/brook/brooklink.go index 8f003ca5fc..d5def132ee 100644 --- a/brook/brooklink.go +++ b/brook/brooklink.go @@ -18,6 +18,7 @@ import ( "crypto/tls" "crypto/x509" "errors" + "io" "net" "net/url" "os/exec" @@ -319,6 +320,7 @@ func (x *BrookLink) TCPHandle(s *socks5.Server, c *net.TCPConn, r *socks5.Reques if err != nil { return err } + io.Copy(io.Discard, c) return nil } return socks5.ErrUnsupportCmd diff --git a/brook/cli/brook/main.go b/brook/cli/brook/main.go index 2dc81ad790..18f6891684 100644 --- a/brook/cli/brook/main.go +++ b/brook/cli/brook/main.go @@ -52,7 +52,7 @@ func main() { df := func() {} app := cli.NewApp() app.Name = "Brook" - app.Version = "20240404" + app.Version = "20240606" app.Usage = "A cross-platform programmable network tool" app.Authors = []*cli.Author{ { diff --git a/brook/docs/images/user-system.png b/brook/docs/images/user-system.png new file mode 100644 index 0000000000..b43112cc07 Binary files /dev/null and b/brook/docs/images/user-system.png differ diff --git a/brook/protocol/user-system.md b/brook/protocol/user-system.md new file mode 100644 index 0000000000..e0e50cdb18 --- /dev/null +++ b/brook/protocol/user-system.md @@ -0,0 +1,81 @@ +# User System + +⚠️ Currently, this feature is experimental. At present, only this [brook_linux_amd64.20240606](https://github.com/txthinking/bash/releases/download/v20221005/brook_linux_amd64.20240606) and [tun2brook](https://github.com/txthinking/tun2brook) support it. + +This content introduces how to develop a user system with Brook. Your system only needs to focus on two concepts: **Token** and **User API**. To support user system, you **must use brook server/wsserver/wssserver/quicserver with the brook protocol**. + + + +## Token + +The concept of a token is similar to the user authentication systems of many other systems, such as cookie, session, it represents an identifier that is visible to the user, so **it shoud be unpredictable**. For example, suppose your user system has the concept of an auto-incrementing user ID. You might need to encrypt this user ID to generate a token to be placed on the client side. Alternatively, if your user ID is a UUID, or if you have an auto-incrementing user ID along with an additional UUID, you can also use the UUID directly as a token. This entirely depends on your own decision. If you have developed any user authentication system, this is basic knowledge. No matter what method you use to generate the token, you need to **encode it as hexadecimal**. The length should be controlled at around a few dozen bytes, do not make it too long. + +For example, encrypt user id or make session, and encode in hexadecimal: + +``` +hex_encode(your_encrypt_or_session_function(user id)) +// 3ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb273ae6afc9fad94abd8985d8ecc77afb27 // 48 bytes token +``` + +For example, UUID: + +```javascript +crypto.randomUUID().replaceAll('-', '') +// 3ae6afc9fad94abd8985d8ecc77afb27 // 16 bytes token +``` + +## User API + +Your system must provide an API for Brook Server to validate token. For example: `https://your-api-server.com/a_unpredictable_path`, yes, it is recommended to add an unpredictable path to your https API, of course, you can also use the http api for internal network communication. Brook Server will send GET request to your User API to check if token is valid, the request format is `https://your-api-server.com/a_unpredictable_path?token=xxx`. When the response is 200, the body should be the user's unique identifier, such as user ID; all other status codes are considered to represent an invalid user, and in these cases, the body should be a string describing the error. + +For example, your User API is: + +``` +https://your-api-server.com/a_unpredictable_path +``` + +Brook Server will send GET request with token to your User API: + +``` +GET https://your-api-server.com/a_unpredictable_path?token=xxx +``` + +If the token is valid, your User API should response status code 200 and body should be user's unique identifier, such as user ID 9: + +``` +HTTP/1.1 200 OK +Content-Length: 1 +Content-Type: text/plain; charset=utf-8 + +9 +``` + +If the token is invalid, or because of any other reasons, the service cannot be provided to this user, such as the user has expired, your User API should response status code non-200 and body should be the short reason: + +``` +HTTP/1.1 400 BAD REQUEST +Content-Length: 22 +Content-Type: text/plain; charset=utf-8 + +The user 9 has expired +``` + +## Run Brook Server with your User API + +``` +brook --serverLog /path/to/log.txt --userAPI https://your-api-server.com/a_unpredictable_path server --listen :9999 --password hello +``` + +You can count the traffic of each user from serverLog + +``` +{"bytes":"2190","dst":"8.8.8.8:53","from":"34.105.110.232:49514","network":"tcp","time":"2024-02-26T09:56:12Z","user":"9"} +{"bytes":"2237","dst":"8.8.8.8:53","from":"34.105.110.232:49331","network":"udp","time":"2024-02-26T09:57:12Z","user":"9"} +``` + +## Generate brook link with token + +``` +brook link --server 1.2.3.4:9999 --password hello --token xxx +``` + diff --git a/clash-meta/component/iface/iface.go b/clash-meta/component/iface/iface.go index dd932b4629..1d0219dfac 100644 --- a/clash-meta/component/iface/iface.go +++ b/clash-meta/component/iface/iface.go @@ -40,16 +40,23 @@ func ResolveInterface(name string) (*Interface, error) { ipNets := make([]netip.Prefix, 0, len(addrs)) for _, addr := range addrs { - ipNet := addr.(*net.IPNet) - ip, _ := netip.AddrFromSlice(ipNet.IP) - - ones, bits := ipNet.Mask.Size() - if bits == 32 { + var pf netip.Prefix + switch ipNet := addr.(type) { + case *net.IPNet: + ip, _ := netip.AddrFromSlice(ipNet.IP) + ones, bits := ipNet.Mask.Size() + if bits == 32 { + ip = ip.Unmap() + } + pf = netip.PrefixFrom(ip, ones) + case *net.IPAddr: + ip, _ := netip.AddrFromSlice(ipNet.IP) ip = ip.Unmap() + pf = netip.PrefixFrom(ip, ip.BitLen()) + } + if pf.IsValid() { + ipNets = append(ipNets, pf) } - - pf := netip.PrefixFrom(ip, ones) - ipNets = append(ipNets, pf) } r[iface.Name] = &Interface{ diff --git a/clash-meta/config/config.go b/clash-meta/config/config.go index ca86649161..ca179ed051 100644 --- a/clash-meta/config/config.go +++ b/clash-meta/config/config.go @@ -265,6 +265,7 @@ type RawTun struct { EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint_independent_nat,omitempty"` UDPTimeout int64 `yaml:"udp-timeout" json:"udp_timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex int `yaml:"table-index" json:"table-index"` } type RawTuicServer struct { @@ -1448,6 +1449,7 @@ func parseTun(rawTun RawTun, general *General) error { EndpointIndependentNat: rawTun.EndpointIndependentNat, UDPTimeout: rawTun.UDPTimeout, FileDescriptor: rawTun.FileDescriptor, + TableIndex: rawTun.TableIndex, } return nil diff --git a/clash-meta/hub/route/configs.go b/clash-meta/hub/route/configs.go index ec0b464ce4..653e43519b 100644 --- a/clash-meta/hub/route/configs.go +++ b/clash-meta/hub/route/configs.go @@ -91,6 +91,7 @@ type tunSchema struct { EndpointIndependentNat *bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` UDPTimeout *int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor *int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex *int `yaml:"table-index" json:"table-index"` } type tuicServerSchema struct { @@ -209,6 +210,9 @@ func pointerOrDefaultTun(p *tunSchema, def LC.Tun) LC.Tun { if p.FileDescriptor != nil { def.FileDescriptor = *p.FileDescriptor } + if p.TableIndex != nil { + def.TableIndex = *p.TableIndex + } } return def } diff --git a/clash-meta/listener/config/tun.go b/clash-meta/listener/config/tun.go index 1772c6f5b4..7467e4a6a7 100644 --- a/clash-meta/listener/config/tun.go +++ b/clash-meta/listener/config/tun.go @@ -49,4 +49,5 @@ type Tun struct { EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex int `yaml:"table-index" json:"table-index"` } diff --git a/clash-meta/listener/inbound/tun.go b/clash-meta/listener/inbound/tun.go index a1fdebfa4a..51747c4629 100644 --- a/clash-meta/listener/inbound/tun.go +++ b/clash-meta/listener/inbound/tun.go @@ -40,6 +40,7 @@ type TunOption struct { EndpointIndependentNat bool `inbound:"endpoint_independent_nat,omitempty"` UDPTimeout int64 `inbound:"udp_timeout,omitempty"` FileDescriptor int `inbound:"file-descriptor,omitempty"` + TableIndex int `inbound:"table-index,omitempty"` } func (o TunOption) Equal(config C.InboundConfig) bool { @@ -118,6 +119,7 @@ func NewTun(options *TunOption) (*Tun, error) { EndpointIndependentNat: options.EndpointIndependentNat, UDPTimeout: options.UDPTimeout, FileDescriptor: options.FileDescriptor, + TableIndex: options.TableIndex, }, }, nil } diff --git a/clash-meta/listener/listener.go b/clash-meta/listener/listener.go index ac60297196..e35061882d 100644 --- a/clash-meta/listener/listener.go +++ b/clash-meta/listener/listener.go @@ -823,7 +823,8 @@ func hasTunConfigChange(tunConf *LC.Tun) bool { LastTunConf.StrictRoute != tunConf.StrictRoute || LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat || LastTunConf.UDPTimeout != tunConf.UDPTimeout || - LastTunConf.FileDescriptor != tunConf.FileDescriptor { + LastTunConf.FileDescriptor != tunConf.FileDescriptor || + LastTunConf.TableIndex != tunConf.TableIndex { return true } diff --git a/clash-meta/listener/sing_tun/server.go b/clash-meta/listener/sing_tun/server.go index cc26d37dcc..96ec1573f2 100644 --- a/clash-meta/listener/sing_tun/server.go +++ b/clash-meta/listener/sing_tun/server.go @@ -112,6 +112,10 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis } else { udpTimeout = int64(sing.UDPTimeout.Seconds()) } + tableIndex := options.TableIndex + if tableIndex == 0 { + tableIndex = 2022 + } includeUID := uidToRange(options.IncludeUID) if len(options.IncludeUIDRange) > 0 { var err error @@ -225,7 +229,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis ExcludePackage: options.ExcludePackage, FileDescriptor: options.FileDescriptor, InterfaceMonitor: defaultInterfaceMonitor, - TableIndex: 2022, + TableIndex: tableIndex, } err = l.buildAndroidRules(&tunOptions) diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index eb6303ebfa..605b7301a3 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -322,9 +322,9 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 81a7fd02ea..171f1818fc 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.18.1", - "mihomo_alpha": "alpha-9c08e93", + "mihomo_alpha": "alpha-d56a439", "clash_rs": "v0.1.15", "clash_premium": "2023-09-05-gdcc8d87" }, @@ -36,5 +36,5 @@ "darwin-x64": "clash-darwin-amd64-n{}.gz" } }, - "updated_at": "2024-03-21T22:24:56.585Z" + "updated_at": "2024-03-23T22:23:53.725Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 6d105e287a..dcaba6e2c2 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -141,7 +141,7 @@ "prettier-plugin-toml": "2.0.1", "sass": "1.72.0", "shikiji": "0.10.2", - "stylelint": "16.2.1", + "stylelint": "16.3.0", "stylelint-config-html": "1.1.0", "stylelint-config-recess-order": "5.0.0", "stylelint-config-standard": "36.0.0", @@ -151,7 +151,7 @@ "telegraf": "4.16.3", "tsx": "4.7.1", "typescript": "5.4.3", - "vite": "5.2.4", + "vite": "5.2.5", "vite-plugin-monaco-editor": "1.1.0", "vite-plugin-svgr": "4.2.0" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 734ccdb03d..a8a09bf3ee 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -141,7 +141,7 @@ devDependencies: version: 7.3.1(eslint@8.57.0)(typescript@5.4.3) '@vitejs/plugin-react': specifier: 4.2.1 - version: 4.2.1(vite@5.2.4) + version: 4.2.1(vite@5.2.5) adm-zip: specifier: 0.5.12 version: 0.5.12 @@ -239,26 +239,26 @@ devDependencies: specifier: 0.10.2 version: 0.10.2 stylelint: - specifier: 16.2.1 - version: 16.2.1(typescript@5.4.3) + specifier: 16.3.0 + version: 16.3.0(typescript@5.4.3) stylelint-config-html: specifier: 1.1.0 - version: 1.1.0(postcss-html@1.6.0)(stylelint@16.2.1) + version: 1.1.0(postcss-html@1.6.0)(stylelint@16.3.0) stylelint-config-recess-order: specifier: 5.0.0 - version: 5.0.0(stylelint@16.2.1) + version: 5.0.0(stylelint@16.3.0) stylelint-config-standard: specifier: 36.0.0 - version: 36.0.0(stylelint@16.2.1) + version: 36.0.0(stylelint@16.3.0) stylelint-declaration-block-no-ignored-properties: specifier: 2.8.0 - version: 2.8.0(stylelint@16.2.1) + version: 2.8.0(stylelint@16.3.0) stylelint-order: specifier: 6.0.4 - version: 6.0.4(stylelint@16.2.1) + version: 6.0.4(stylelint@16.3.0) stylelint-scss: specifier: 6.2.1 - version: 6.2.1(stylelint@16.2.1) + version: 6.2.1(stylelint@16.3.0) telegraf: specifier: 4.16.3 version: 4.16.3 @@ -269,14 +269,14 @@ devDependencies: specifier: 5.4.3 version: 5.4.3 vite: - specifier: 5.2.4 - version: 5.2.4(@types/node@20.11.30)(sass@1.72.0) + specifier: 5.2.5 + version: 5.2.5(@types/node@20.11.30)(sass@1.72.0) vite-plugin-monaco-editor: specifier: npm:vite-plugin-monaco-editor-new@1.1.3 version: /vite-plugin-monaco-editor-new@1.1.3(monaco-editor@0.47.0) vite-plugin-svgr: specifier: 4.2.0 - version: 4.2.0(typescript@5.4.3)(vite@5.2.4) + version: 4.2.0(typescript@5.4.3)(vite@5.2.5) packages: @@ -703,38 +703,38 @@ packages: chalk: 5.3.0 dev: true - /@csstools/css-parser-algorithms@2.5.0(@csstools/css-tokenizer@2.2.3): - resolution: {integrity: sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ==} + /@csstools/css-parser-algorithms@2.6.1(@csstools/css-tokenizer@2.2.4): + resolution: {integrity: sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - '@csstools/css-tokenizer': ^2.2.3 + '@csstools/css-tokenizer': ^2.2.4 dependencies: - '@csstools/css-tokenizer': 2.2.3 + '@csstools/css-tokenizer': 2.2.4 dev: true - /@csstools/css-tokenizer@2.2.3: - resolution: {integrity: sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg==} + /@csstools/css-tokenizer@2.2.4: + resolution: {integrity: sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==} engines: {node: ^14 || ^16 || >=18} dev: true - /@csstools/media-query-list-parser@2.1.7(@csstools/css-parser-algorithms@2.5.0)(@csstools/css-tokenizer@2.2.3): - resolution: {integrity: sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ==} + /@csstools/media-query-list-parser@2.1.9(@csstools/css-parser-algorithms@2.6.1)(@csstools/css-tokenizer@2.2.4): + resolution: {integrity: sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==} engines: {node: ^14 || ^16 || >=18} peerDependencies: - '@csstools/css-parser-algorithms': ^2.5.0 - '@csstools/css-tokenizer': ^2.2.3 + '@csstools/css-parser-algorithms': ^2.6.1 + '@csstools/css-tokenizer': ^2.2.4 dependencies: - '@csstools/css-parser-algorithms': 2.5.0(@csstools/css-tokenizer@2.2.3) - '@csstools/css-tokenizer': 2.2.3 + '@csstools/css-parser-algorithms': 2.6.1(@csstools/css-tokenizer@2.2.4) + '@csstools/css-tokenizer': 2.2.4 dev: true - /@csstools/selector-specificity@3.0.1(postcss-selector-parser@6.0.15): - resolution: {integrity: sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww==} + /@csstools/selector-specificity@3.0.2(postcss-selector-parser@6.0.16): + resolution: {integrity: sha512-RpHaZ1h9LE7aALeQXmXrJkRG84ZxIsctEN2biEUmFyKpzFM3zZ35eUMcIzZFsw/2olQE6v69+esEqU2f1MKycg==} engines: {node: ^14 || ^16 || >=18} peerDependencies: postcss-selector-parser: ^6.0.13 dependencies: - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 dev: true /@ctrl/tinycolor@4.0.3: @@ -785,6 +785,10 @@ packages: tslib: 2.6.2 dev: false + /@dual-bundle/import-meta-resolve@4.0.0: + resolution: {integrity: sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==} + dev: true + /@emotion/babel-plugin@11.11.0: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: @@ -2235,10 +2239,6 @@ packages: '@types/estree': 1.0.5 dev: false - /@types/estree@1.0.3: - resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} - dev: false - /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -2474,7 +2474,7 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - /@vitejs/plugin-react@4.2.1(vite@5.2.4): + /@vitejs/plugin-react@4.2.1(vite@5.2.5): resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2485,7 +2485,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 5.2.4(@types/node@20.11.30)(sass@1.72.0) + vite: 5.2.5(@types/node@20.11.30)(sass@1.72.0) transitivePeerDependencies: - supports-color dev: true @@ -4411,7 +4411,7 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.0 + ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 dev: true @@ -4501,7 +4501,7 @@ packages: /hast-util-to-jsx-runtime@2.3.0: resolution: {integrity: sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==} dependencies: - '@types/estree': 1.0.3 + '@types/estree': 1.0.5 '@types/hast': 3.0.4 '@types/unist': 3.0.2 comma-separated-tokens: 2.0.3 @@ -4607,6 +4607,11 @@ packages: engines: {node: '>= 4'} dev: true + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + /immutable@4.0.0: resolution: {integrity: sha512-zIE9hX70qew5qTUjSS7wi1iwj/l7+m54KWU247nhM3v806UdGj1yDndXj+IOYxxtW9zyLI+xqFNZjTuDaLUqFw==} dev: true @@ -5096,6 +5101,10 @@ packages: resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==} dev: true + /known-css-properties@0.30.0: + resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} + dev: true + /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -5373,8 +5382,8 @@ packages: engines: {node: '>=16.10'} dev: true - /meow@13.1.0: - resolution: {integrity: sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA==} + /meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} dev: true @@ -6036,6 +6045,14 @@ packages: util-deprecate: 1.0.2 dev: true + /postcss-selector-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + dev: true + /postcss-sorting@8.0.2(postcss@8.4.38): resolution: {integrity: sha512-M9dkSrmU00t/jK7rF6BZSZauA5MAaBW4i5EnJXspMwt4iqTh/L9j6fgMnbElEOfyRyfLfVbIHj/R52zHzAPe1Q==} peerDependencies: @@ -6803,7 +6820,7 @@ packages: inline-style-parser: 0.2.2 dev: false - /stylelint-config-html@1.1.0(postcss-html@1.6.0)(stylelint@16.2.1): + /stylelint-config-html@1.1.0(postcss-html@1.6.0)(stylelint@16.3.0): resolution: {integrity: sha512-IZv4IVESjKLumUGi+HWeb7skgO6/g4VMuAYrJdlqQFndgbj6WJAXPhaysvBiXefX79upBdQVumgYcdd17gCpjQ==} engines: {node: ^12 || >=14} peerDependencies: @@ -6811,57 +6828,57 @@ packages: stylelint: '>=14.0.0' dependencies: postcss-html: 1.6.0 - stylelint: 16.2.1(typescript@5.4.3) + stylelint: 16.3.0(typescript@5.4.3) dev: true - /stylelint-config-recess-order@5.0.0(stylelint@16.2.1): + /stylelint-config-recess-order@5.0.0(stylelint@16.3.0): resolution: {integrity: sha512-D+/Got844O96No2mj/H2NhLjj555iKAy/Mea+JCerfKB9TBKQW3/IudSVkTCxE4QiRDLldfH15x6FH1D1Anjhw==} peerDependencies: stylelint: '>=16' dependencies: - stylelint: 16.2.1(typescript@5.4.3) - stylelint-order: 6.0.4(stylelint@16.2.1) + stylelint: 16.3.0(typescript@5.4.3) + stylelint-order: 6.0.4(stylelint@16.3.0) dev: true - /stylelint-config-recommended@14.0.0(stylelint@16.2.1): + /stylelint-config-recommended@14.0.0(stylelint@16.3.0): resolution: {integrity: sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==} engines: {node: '>=18.12.0'} peerDependencies: stylelint: ^16.0.0 dependencies: - stylelint: 16.2.1(typescript@5.4.3) + stylelint: 16.3.0(typescript@5.4.3) dev: true - /stylelint-config-standard@36.0.0(stylelint@16.2.1): + /stylelint-config-standard@36.0.0(stylelint@16.3.0): resolution: {integrity: sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==} engines: {node: '>=18.12.0'} peerDependencies: stylelint: ^16.1.0 dependencies: - stylelint: 16.2.1(typescript@5.4.3) - stylelint-config-recommended: 14.0.0(stylelint@16.2.1) + stylelint: 16.3.0(typescript@5.4.3) + stylelint-config-recommended: 14.0.0(stylelint@16.3.0) dev: true - /stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.2.1): + /stylelint-declaration-block-no-ignored-properties@2.8.0(stylelint@16.3.0): resolution: {integrity: sha512-Ws8Cav7Y+SPN0JsV407LrnNXWOrqGjxShf+37GBtnU/C58Syve9c0+I/xpLcFOosST3ternykn3Lp77f3ITnFw==} engines: {node: '>=6'} peerDependencies: stylelint: ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: - stylelint: 16.2.1(typescript@5.4.3) + stylelint: 16.3.0(typescript@5.4.3) dev: true - /stylelint-order@6.0.4(stylelint@16.2.1): + /stylelint-order@6.0.4(stylelint@16.3.0): resolution: {integrity: sha512-0UuKo4+s1hgQ/uAxlYU4h0o0HS4NiQDud0NAUNI0aa8FJdmYHA5ZZTFHiV5FpmE3071e9pZx5j0QpVJW5zOCUA==} peerDependencies: stylelint: ^14.0.0 || ^15.0.0 || ^16.0.1 dependencies: postcss: 8.4.38 postcss-sorting: 8.0.2(postcss@8.4.38) - stylelint: 16.2.1(typescript@5.4.3) + stylelint: 16.3.0(typescript@5.4.3) dev: true - /stylelint-scss@6.2.1(stylelint@16.2.1): + /stylelint-scss@6.2.1(stylelint@16.3.0): resolution: {integrity: sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw==} engines: {node: '>=18.12.0'} peerDependencies: @@ -6872,18 +6889,19 @@ packages: postcss-resolve-nested-selector: 0.1.1 postcss-selector-parser: 6.0.15 postcss-value-parser: 4.2.0 - stylelint: 16.2.1(typescript@5.4.3) + stylelint: 16.3.0(typescript@5.4.3) dev: true - /stylelint@16.2.1(typescript@5.4.3): - resolution: {integrity: sha512-SfIMGFK+4n7XVAyv50CpVfcGYWG4v41y6xG7PqOgQSY8M/PgdK0SQbjWFblxjJZlN9jNq879mB4BCZHJRIJ1hA==} + /stylelint@16.3.0(typescript@5.4.3): + resolution: {integrity: sha512-hqC6xNTbQ5HRGQXfIW4HwXcx09raIFz4W4XFbraeqWqYRVVY/ibYvI0dsu0ORMQY8re2bpDdCAeIa2cm+QJ4Sw==} engines: {node: '>=18.12.0'} hasBin: true dependencies: - '@csstools/css-parser-algorithms': 2.5.0(@csstools/css-tokenizer@2.2.3) - '@csstools/css-tokenizer': 2.2.3 - '@csstools/media-query-list-parser': 2.1.7(@csstools/css-parser-algorithms@2.5.0)(@csstools/css-tokenizer@2.2.3) - '@csstools/selector-specificity': 3.0.1(postcss-selector-parser@6.0.15) + '@csstools/css-parser-algorithms': 2.6.1(@csstools/css-tokenizer@2.2.4) + '@csstools/css-tokenizer': 2.2.4 + '@csstools/media-query-list-parser': 2.1.9(@csstools/css-parser-algorithms@2.6.1)(@csstools/css-tokenizer@2.2.4) + '@csstools/selector-specificity': 3.0.2(postcss-selector-parser@6.0.16) + '@dual-bundle/import-meta-resolve': 4.0.0 balanced-match: 2.0.0 colord: 2.9.3 cosmiconfig: 9.0.0(typescript@5.4.3) @@ -6897,19 +6915,19 @@ packages: globby: 11.1.0 globjoin: 0.1.4 html-tags: 3.3.1 - ignore: 5.3.0 + ignore: 5.3.1 imurmurhash: 0.1.4 is-plain-object: 5.0.0 - known-css-properties: 0.29.0 + known-css-properties: 0.30.0 mathml-tag-names: 2.1.3 - meow: 13.1.0 + meow: 13.2.0 micromatch: 4.0.5 normalize-path: 3.0.0 picocolors: 1.0.0 postcss: 8.4.38 postcss-resolve-nested-selector: 0.1.1 postcss-safe-parser: 7.0.0(postcss@8.4.38) - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 postcss-value-parser: 4.2.0 resolve-from: 5.0.0 string-width: 4.2.3 @@ -7334,7 +7352,7 @@ packages: monaco-editor: 0.47.0 dev: true - /vite-plugin-svgr@4.2.0(typescript@5.4.3)(vite@5.2.4): + /vite-plugin-svgr@4.2.0(typescript@5.4.3)(vite@5.2.5): resolution: {integrity: sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==} peerDependencies: vite: ^2.6.0 || 3 || 4 || 5 @@ -7342,15 +7360,15 @@ packages: '@rollup/pluginutils': 5.0.5 '@svgr/core': 8.1.0(typescript@5.4.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0) - vite: 5.2.4(@types/node@20.11.30)(sass@1.72.0) + vite: 5.2.5(@types/node@20.11.30)(sass@1.72.0) transitivePeerDependencies: - rollup - supports-color - typescript dev: true - /vite@5.2.4(@types/node@20.11.30)(sass@1.72.0): - resolution: {integrity: sha512-vjFghvHWidBTinu5TCymJk/lRHlR5ljqB83yugr0HA1xspUPdOZHqbqDLnZ8f9/jINrtFHTCYYyIUi+o+Q5iyg==} + /vite@5.2.5(@types/node@20.11.30)(sass@1.72.0): + resolution: {integrity: sha512-a+rTAqkMmJ2hQpC6dfAyyc5M0YLH3BGZKLpA6pU9AhzlcK1YZS8P/ov9OcdHxaf+j0sM0DIh/txH7ydTHUpISg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: diff --git a/echo/internal/cli/config.go b/echo/internal/cli/config.go index 9dcffc1460..0822271454 100644 --- a/echo/internal/cli/config.go +++ b/echo/internal/cli/config.go @@ -102,7 +102,10 @@ func MustStartComponents(mainCtx context.Context, cfg *config.Config) { } go func() { metrics.EhcoAlive.Set(metrics.EhcoAliveStateRunning) - cliLogger.Fatalf("StartRelayServer meet err=%s", rs.Start(mainCtx)) + sErr := rs.Start(mainCtx) + if sErr != nil { + cliLogger.Fatalf("StartRelayServer meet err=%s", sErr.Error()) + } }() if cfg.NeedStartWebServer() { diff --git a/hysteria/app/go.mod b/hysteria/app/go.mod index 6b5d2c3d4a..a5025c1de3 100644 --- a/hysteria/app/go.mod +++ b/hysteria/app/go.mod @@ -19,7 +19,7 @@ require ( ) require ( - github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d // indirect + github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 // indirect github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -50,7 +50,7 @@ require ( github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect go.uber.org/atomic v1.11.0 // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect golang.org/x/crypto v0.19.0 // indirect diff --git a/hysteria/app/go.sum b/hysteria/app/go.sum index 152e338712..4f2b0fed27 100644 --- a/hysteria/app/go.sum +++ b/hysteria/app/go.sum @@ -40,8 +40,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjgzx9vOcyCqsOY3c9kofDZ1n+qaw35ZY= github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM= -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI= -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 h1:+ZSzRxSMg1+fLTQKcIUvD2cCCgS+1rtyRhs+NL5oBgA= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822/go.mod h1:j3QaAM7sVJqptDQyIQRWA6mASCfuxoHJszn67JQh1GE= github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad h1:QzQ2sKpc9o42HNRR8ukM5uMC/RzR2HgZd/Nvaqol2C0= github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= @@ -259,8 +259,8 @@ go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0 go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -440,6 +440,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/hysteria/core/go.mod b/hysteria/core/go.mod index 76bc92775e..91d4cb9fa4 100644 --- a/hysteria/core/go.mod +++ b/hysteria/core/go.mod @@ -3,11 +3,11 @@ module github.com/apernet/hysteria/core go 1.21 require ( - github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d + github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 github.com/stretchr/testify v1.8.4 go.uber.org/goleak v1.2.1 golang.org/x/exp v0.0.0-20221205204356-47842c84f3db - golang.org/x/time v0.4.0 + golang.org/x/time v0.5.0 ) require ( @@ -20,7 +20,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/stretchr/objx v0.5.0 // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.21.0 // indirect diff --git a/hysteria/core/go.sum b/hysteria/core/go.sum index 7b21427b8c..908b18e2cd 100644 --- a/hysteria/core/go.sum +++ b/hysteria/core/go.sum @@ -1,5 +1,5 @@ -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI= -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 h1:+ZSzRxSMg1+fLTQKcIUvD2cCCgS+1rtyRhs+NL5oBgA= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822/go.mod h1:j3QaAM7sVJqptDQyIQRWA6mASCfuxoHJszn67JQh1GE= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -43,8 +43,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= @@ -58,8 +58,8 @@ golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= -golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc= golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= diff --git a/hysteria/core/internal/integration_tests/close_test.go b/hysteria/core/internal/integration_tests/close_test.go index 4160b3cd5b..ab6d016ac6 100644 --- a/hysteria/core/internal/integration_tests/close_test.go +++ b/hysteria/core/internal/integration_tests/close_test.go @@ -2,6 +2,7 @@ package integration_tests import ( "io" + "sync" "testing" "time" @@ -48,13 +49,14 @@ func TestClientServerTCPClose(t *testing.T) { // Server outbound connection should write the same thing, then close. sobConn := mocks.NewMockConn(t) sobConnCh := make(chan struct{}) // For close signal only + sobConnChCloseFunc := sync.OnceFunc(func() { close(sobConnCh) }) sobConn.EXPECT().Read(mock.Anything).RunAndReturn(func(bs []byte) (int, error) { <-sobConnCh return 0, io.EOF }) sobConn.EXPECT().Write([]byte("happy")).Return(5, nil) sobConn.EXPECT().Close().RunAndReturn(func() error { - close(sobConnCh) + sobConnChCloseFunc() return nil }) serverOb.EXPECT().TCP(addr).Return(sobConn, nil).Once() @@ -133,6 +135,7 @@ func TestClientServerUDPIdleTimeout(t *testing.T) { // to trigger the server's UDP idle timeout. sobConn := mocks.NewMockUDPConn(t) sobConnCh := make(chan []byte, 1) + sobConnChCloseFunc := sync.OnceFunc(func() { close(sobConnCh) }) sobConn.EXPECT().ReadFrom(mock.Anything).RunAndReturn(func(bs []byte) (int, string, error) { d := <-sobConnCh if d == nil { @@ -167,7 +170,7 @@ func TestClientServerUDPIdleTimeout(t *testing.T) { } // Now we wait for 3 seconds, the server should close the UDP session. sobConn.EXPECT().Close().RunAndReturn(func() error { - close(sobConnCh) + sobConnChCloseFunc() return nil }) eventLogger.EXPECT().UDPError(mock.Anything, mock.Anything, uint32(1), nil).Once() diff --git a/hysteria/core/internal/integration_tests/trafficlogger_test.go b/hysteria/core/internal/integration_tests/trafficlogger_test.go index ff1d66ee81..abbea8cdd3 100644 --- a/hysteria/core/internal/integration_tests/trafficlogger_test.go +++ b/hysteria/core/internal/integration_tests/trafficlogger_test.go @@ -2,6 +2,7 @@ package integration_tests import ( "io" + "sync" "testing" "time" @@ -46,6 +47,7 @@ func TestClientServerTrafficLoggerTCP(t *testing.T) { sobConn := mocks.NewMockConn(t) sobConnCh := make(chan []byte, 1) + sobConnChCloseFunc := sync.OnceFunc(func() { close(sobConnCh) }) sobConn.EXPECT().Read(mock.Anything).RunAndReturn(func(bs []byte) (int, error) { b := <-sobConnCh if b == nil { @@ -55,9 +57,9 @@ func TestClientServerTrafficLoggerTCP(t *testing.T) { } }) sobConn.EXPECT().Close().RunAndReturn(func() error { - close(sobConnCh) + sobConnChCloseFunc() return nil - }).Once() + }) serverOb.EXPECT().TCP(addr).Return(sobConn, nil).Once() conn, err := c.TCP(addr) @@ -125,6 +127,7 @@ func TestClientServerTrafficLoggerUDP(t *testing.T) { sobConn := mocks.NewMockUDPConn(t) sobConnCh := make(chan []byte, 1) + sobConnChCloseFunc := sync.OnceFunc(func() { close(sobConnCh) }) sobConn.EXPECT().ReadFrom(mock.Anything).RunAndReturn(func(bs []byte) (int, string, error) { b := <-sobConnCh if b == nil { @@ -134,9 +137,9 @@ func TestClientServerTrafficLoggerUDP(t *testing.T) { } }) sobConn.EXPECT().Close().RunAndReturn(func() error { - close(sobConnCh) + sobConnChCloseFunc() return nil - }).Once() + }) serverOb.EXPECT().UDP(addr).Return(sobConn, nil).Once() conn, err := c.UDP() diff --git a/hysteria/extras/go.mod b/hysteria/extras/go.mod index 3bb0dcde0c..bc21044510 100644 --- a/hysteria/extras/go.mod +++ b/hysteria/extras/go.mod @@ -15,7 +15,7 @@ require ( ) require ( - github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d // indirect + github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect @@ -25,7 +25,7 @@ require ( github.com/quic-go/qpack v0.4.0 // indirect github.com/stretchr/objx v0.5.0 // indirect github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/sys v0.17.0 // indirect diff --git a/hysteria/extras/go.sum b/hysteria/extras/go.sum index c635709cd5..390cc97801 100644 --- a/hysteria/extras/go.sum +++ b/hysteria/extras/go.sum @@ -1,5 +1,5 @@ -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI= -github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822 h1:+ZSzRxSMg1+fLTQKcIUvD2cCCgS+1rtyRhs+NL5oBgA= +github.com/apernet/quic-go v0.42.1-0.20240323215309-32a339817822/go.mod h1:j3QaAM7sVJqptDQyIQRWA6mASCfuxoHJszn67JQh1GE= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= @@ -54,8 +54,8 @@ github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301/go.mod h1:ntmMHL github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= @@ -95,6 +95,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/lede/target/linux/rockchip/Makefile b/lede/target/linux/rockchip/Makefile index 9157b28c66..029d93f6ee 100644 --- a/lede/target/linux/rockchip/Makefile +++ b/lede/target/linux/rockchip/Makefile @@ -7,8 +7,8 @@ BOARDNAME:=Rockchip FEATURES:=ext4 audio usb usbgadget display gpio fpu pci pcie rootfs-part boot-part squashfs SUBTARGETS:=armv8 -KERNEL_PATCHVER:=5.15 -KERNEL_TESTING_PATCHVER:=6.1 +KERNEL_PATCHVER:=6.1 +KERNEL_TESTING_PATCHVER:=6.6 define Target/Description Build firmware image for Rockchip SoC devices. diff --git a/lede/target/linux/rockchip/armv8/config-6.6 b/lede/target/linux/rockchip/armv8/config-6.6 new file mode 100644 index 0000000000..32773253fd --- /dev/null +++ b/lede/target/linux/rockchip/armv8/config-6.6 @@ -0,0 +1,726 @@ +CONFIG_64BIT=y +CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y +CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y +CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_ARCH_FORCE_MAX_ORDER=10 +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_KEEP_MEMBLOCK=y +CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=33 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_ARCH_SELECTS_KEXEC_FILE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_STACKWALK=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARCH_WANTS_NO_INSTR=y +CONFIG_ARCH_WANTS_THP_SWAP=y +CONFIG_ARC_EMAC_CORE=y +CONFIG_ARM64=y +CONFIG_ARM64_4K_PAGES=y +CONFIG_ARM64_CNP=y +CONFIG_ARM64_EPAN=y +CONFIG_ARM64_ERRATUM_1742098=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_858921=y +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_PAN=y +CONFIG_ARM64_PA_BITS=48 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PTR_AUTH=y +CONFIG_ARM64_PTR_AUTH_KERNEL=y +CONFIG_ARM64_RAS_EXTN=y +CONFIG_ARM64_SVE=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set +CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_ARM64_VA_BITS=48 +# CONFIG_ARM64_VA_BITS_39 is not set +CONFIG_ARM64_VA_BITS_48=y +CONFIG_ARM64_WORKAROUND_CLEAN_CACHE=y +# CONFIG_ARMV8_DEPRECATED is not set +CONFIG_ARM_AMBA=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +CONFIG_ARM_MHU=y +# CONFIG_ARM_MHU_V2 is not set +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE_DOMAIN=y +CONFIG_ARM_PSCI_FW=y +CONFIG_ARM_RK3328_DMC_DEVFREQ=y +# CONFIG_ARM_RK3399_DMC_DEVFREQ is not set +# CONFIG_ARM_SCMI_CPUFREQ is not set +CONFIG_ARM_SCMI_HAVE_SHMEM=y +CONFIG_ARM_SCMI_HAVE_TRANSPORT=y +CONFIG_ARM_SCMI_POWER_CONTROL=y +CONFIG_ARM_SCMI_POWER_DOMAIN=y +CONFIG_ARM_SCMI_PROTOCOL=y +# CONFIG_ARM_SCMI_RAW_MODE_SUPPORT is not set +CONFIG_ARM_SCMI_TRANSPORT_MAILBOX=y +CONFIG_ARM_SCMI_TRANSPORT_SMC=y +# CONFIG_ARM_SCMI_TRANSPORT_SMC_ATOMIC_ENABLE is not set +CONFIG_ARM_SCPI_CPUFREQ=y +CONFIG_ARM_SCPI_POWER_DOMAIN=y +CONFIG_ARM_SCPI_PROTOCOL=y +CONFIG_ARM_SMMU=y +CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=y +# CONFIG_ARM_SMMU_LEGACY_DT_BINDINGS is not set +CONFIG_ARM_SMMU_V3=y +# CONFIG_ARM_SMMU_V3_SVA is not set +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BLK_DEV_BSG=y +CONFIG_BLK_DEV_BSGLIB=y +CONFIG_BLK_DEV_BSG_COMMON=y +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_BLK_DEV_INTEGRITY=y +CONFIG_BLK_DEV_INTEGRITY_T10=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_NVME=y +CONFIG_BLK_DEV_PCIESSD_MTIP32XX=y +CONFIG_BLK_DEV_SD=y +CONFIG_BLK_MQ_PCI=y +CONFIG_BLK_PM=y +CONFIG_BRCMSTB_GISB_ARB=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_BUFFER_HEAD=y +CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y +CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y +CONFIG_CC_NO_ARRAY_BOUNDS=y +CONFIG_CHARGER_GPIO=y +# CONFIG_CHARGER_RK817 is not set +CONFIG_CLKSRC_MMIO=y +CONFIG_CLK_PX30=y +CONFIG_CLK_RK3308=y +CONFIG_CLK_RK3328=y +CONFIG_CLK_RK3368=y +CONFIG_CLK_RK3399=y +CONFIG_CLK_RK3568=y +CONFIG_CLK_RK3588=y +CONFIG_CLONE_BACKWARDS=y +CONFIG_CMA=y +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CMA_DEBUG is not set +# CONFIG_CMA_DEBUGFS is not set +CONFIG_CMA_SIZE_MBYTES=64 +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SYSFS is not set +CONFIG_COMMON_CLK=y +CONFIG_COMMON_CLK_RK808=y +CONFIG_COMMON_CLK_ROCKCHIP=y +CONFIG_COMMON_CLK_SCMI=y +CONFIG_COMMON_CLK_SCPI=y +CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1 +CONFIG_COMPAT=y +CONFIG_COMPAT_32BIT_TIME=y +# CONFIG_COMPAT_ALIGNMENT_FIXUPS is not set +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_CONFIGFS_FS=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_CONTEXT_TRACKING=y +CONFIG_CONTEXT_TRACKING_IDLE=y +CONFIG_CONTIG_ALLOC=y +CONFIG_CPUFREQ_DT=y +CONFIG_CPUFREQ_DT_PLATDEV=y +CONFIG_CPU_FREQ=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +CONFIG_CPU_ISOLATION=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_CPU_PM=y +CONFIG_CPU_RMAP=y +CONFIG_CPU_THERMAL=y +CONFIG_CRASH_CORE=y +CONFIG_CRASH_DUMP=y +CONFIG_CRC16=y +# CONFIG_CRC32_SARWATE is not set +CONFIG_CRC32_SLICEBY8=y +CONFIG_CRC64=y +CONFIG_CRC64_ROCKSOFT=y +CONFIG_CRC_T10DIF=y +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_CRC32=y +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC64_ROCKSOFT=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y +CONFIG_CRYPTO_LIB_GF128MUL=y +CONFIG_CRYPTO_LIB_SHA1=y +CONFIG_CRYPTO_LIB_SHA256=y +CONFIG_CRYPTO_LIB_UTILS=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SM4=y +CONFIG_CRYPTO_SM4_ARM64_CE_BLK=y +CONFIG_CRYPTO_SM4_ARM64_CE_CCM=y +CONFIG_CRYPTO_SM4_ARM64_CE_GCM=y +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI=y +# CONFIG_DEVFREQ_GOV_PASSIVE is not set +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +# CONFIG_DEVFREQ_THERMAL is not set +CONFIG_DEVMEM=y +# CONFIG_DEVPORT is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_DMADEVICES=y +CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y +CONFIG_DMA_CMA=y +CONFIG_DMA_DIRECT_REMAP=y +CONFIG_DMA_ENGINE=y +CONFIG_DMA_OF=y +CONFIG_DMA_OPS=y +CONFIG_DMA_SHARED_BUFFER=y +CONFIG_DNOTIFY=y +CONFIG_DTC=y +CONFIG_DT_IDLE_GENPD=y +CONFIG_DT_IDLE_STATES=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_DWMAC_DWC_QOS_ETH=y +CONFIG_DWMAC_GENERIC=y +CONFIG_DWMAC_ROCKCHIP=y +CONFIG_DW_WATCHDOG=y +CONFIG_EDAC_SUPPORT=y +CONFIG_EEPROM_AT24=y +CONFIG_EMAC_ROCKCHIP=y +CONFIG_ENERGY_MODEL=y +CONFIG_EXCLUSIVE_SYSTEM_RAM=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXTCON=y +CONFIG_F2FS_FS=y +CONFIG_FANOTIFY=y +CONFIG_FHANDLE=y +CONFIG_FIXED_PHY=y +CONFIG_FIX_EARLYCON_MEM=y +# CONFIG_FORTIFY_SOURCE is not set +CONFIG_FRAME_POINTER=y +CONFIG_FS_IOMAP=y +CONFIG_FS_MBCACHE=y +CONFIG_FS_POSIX_ACL=y +CONFIG_FUNCTION_ALIGNMENT=4 +CONFIG_FUNCTION_ALIGNMENT_4B=y +CONFIG_FWNODE_MDIO=y +CONFIG_FW_LOADER_PAGED_BUF=y +CONFIG_FW_LOADER_SYSFS=y +CONFIG_GCC11_NO_ARRAY_BOUNDS=y +CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y +CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_GENERIC_ARCH_TOPOLOGY=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_GENERIC_IOREMAP=y +CONFIG_GENERIC_IRQ_CHIP=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y +CONFIG_GENERIC_PINCONF=y +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GPIOLIB_IRQCHIP=y +CONFIG_GPIO_CDEV=y +CONFIG_GPIO_DWAPB=y +CONFIG_GPIO_GENERIC=y +CONFIG_GPIO_GENERIC_PLATFORM=y +CONFIG_GPIO_ROCKCHIP=y +# CONFIG_HARDENED_USERCOPY is not set +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HID=y +CONFIG_HID_SUPPORT=y +CONFIG_HOTPLUG_CORE_SYNC=y +CONFIG_HOTPLUG_CORE_SYNC_DEAD=y +CONFIG_HOTPLUG_CPU=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_HWMON=y +CONFIG_HWSPINLOCK=y +CONFIG_HW_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_ROCKCHIP=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_RK3X=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_INDIRECT_PIO=y +CONFIG_INPUT=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_FF_MEMLESS=y +CONFIG_INPUT_KEYBOARD=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_MATRIXKMAP=y +# CONFIG_INPUT_MISC is not set +# CONFIG_IOMMUFD is not set +CONFIG_IOMMU_API=y +# CONFIG_IOMMU_DEBUGFS is not set +# CONFIG_IOMMU_DEFAULT_DMA_LAZY is not set +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_DMA=y +CONFIG_IOMMU_IOVA=y +CONFIG_IOMMU_IO_PGTABLE=y +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +# CONFIG_IOMMU_IO_PGTABLE_DART is not set +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +CONFIG_IOMMU_SUPPORT=y +# CONFIG_IO_STRICT_DEVMEM is not set +CONFIG_IO_URING=y +CONFIG_IRQCHIP=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_IRQ_MSI_IOMMU=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_IRQ_WORK=y +CONFIG_JBD2=y +CONFIG_JFFS2_ZLIB=y +CONFIG_JUMP_LABEL=y +CONFIG_KALLSYMS=y +CONFIG_KEXEC_CORE=y +CONFIG_KEXEC_FILE=y +CONFIG_KSM=y +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_SYSCON=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=16 +CONFIG_LIBCRC32C=y +CONFIG_LIBFDT=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_LOCK_DEBUGGING_SUPPORT=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_LOG_BUF_SHIFT=19 +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_MAILBOX=y +# CONFIG_MAILBOX_TEST is not set +CONFIG_MDIO_BUS=y +CONFIG_MDIO_BUS_MUX=y +CONFIG_MDIO_BUS_MUX_GPIO=y +CONFIG_MDIO_BUS_MUX_MMIOREG=y +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_DEVRES=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MFD_CORE=y +# CONFIG_MFD_KHADAS_MCU is not set +CONFIG_MFD_RK8XX=y +CONFIG_MFD_RK8XX_I2C=y +CONFIG_MFD_RK8XX_SPI=y +CONFIG_MFD_SYSCON=y +CONFIG_MIGRATION=y +CONFIG_MMC=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_CQHCI=y +CONFIG_MMC_DW=y +# CONFIG_MMC_DW_BLUEFIELD is not set +# CONFIG_MMC_DW_EXYNOS is not set +# CONFIG_MMC_DW_HI3798CV200 is not set +# CONFIG_MMC_DW_K3 is not set +# CONFIG_MMC_DW_PCI is not set +CONFIG_MMC_DW_PLTFM=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_OF_ARASAN=y +CONFIG_MMC_SDHCI_OF_DWCMSHC=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMU_LAZY_TLB_REFCOUNT=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MOTORCOMM_PHY=y +CONFIG_MQ_IOSCHED_DEADLINE=y +# CONFIG_MTD_CFI is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y +CONFIG_MTD_SPLIT_FIRMWARE=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_FLAGS=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NET_EGRESS=y +CONFIG_NET_FLOW_LIMIT=y +CONFIG_NET_INGRESS=y +CONFIG_NET_SELFTESTS=y +CONFIG_NET_XGRESS=y +CONFIG_NLS=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_NO_HZ_COMMON=y +CONFIG_NO_HZ_IDLE=y +CONFIG_NR_CPUS=256 +CONFIG_NVMEM=y +CONFIG_NVMEM_LAYOUTS=y +CONFIG_NVMEM_ROCKCHIP_EFUSE=y +CONFIG_NVMEM_ROCKCHIP_OTP=y +CONFIG_NVMEM_SYSFS=y +CONFIG_NVME_CORE=y +# CONFIG_NVME_HWMON is not set +# CONFIG_NVME_MULTIPATH is not set +CONFIG_OF=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_GPIO=y +CONFIG_OF_IOMMU=y +CONFIG_OF_IRQ=y +CONFIG_OF_KOBJ=y +CONFIG_OF_MDIO=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_RESOLVE=y +CONFIG_OLD_SIGSUSPEND3=y +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +CONFIG_PADATA=y +CONFIG_PAGE_POOL=y +CONFIG_PAGE_SIZE_LESS_THAN_256KB=y +CONFIG_PAGE_SIZE_LESS_THAN_64KB=y +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_PANIC_TIMEOUT=0 +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PARTITION_PERCPU=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCIE_ROCKCHIP=y +CONFIG_PCIE_ROCKCHIP_DW_HOST=y +CONFIG_PCIE_ROCKCHIP_HOST=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_STUB=y +CONFIG_PCS_XPCS=y +CONFIG_PER_VMA_LOCK=y +CONFIG_PGTABLE_LEVELS=4 +CONFIG_PHYLIB=y +CONFIG_PHYLIB_LEDS=y +CONFIG_PHYLINK=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_PHY_ROCKCHIP_DP=y +# CONFIG_PHY_ROCKCHIP_DPHY_RX0 is not set +CONFIG_PHY_ROCKCHIP_EMMC=y +# CONFIG_PHY_ROCKCHIP_INNO_CSIDPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY is not set +# CONFIG_PHY_ROCKCHIP_INNO_HDMI is not set +CONFIG_PHY_ROCKCHIP_INNO_USB2=y +CONFIG_PHY_ROCKCHIP_NANENG_COMBO_PHY=y +CONFIG_PHY_ROCKCHIP_PCIE=y +CONFIG_PHY_ROCKCHIP_SNPS_PCIE3=y +CONFIG_PHY_ROCKCHIP_TYPEC=y +CONFIG_PHY_ROCKCHIP_USB=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_RK805=y +CONFIG_PINCTRL_ROCKCHIP=y +# CONFIG_PINCTRL_SINGLE is not set +CONFIG_PL330_DMA=y +CONFIG_PLATFORM_MHU=y +CONFIG_PM=y +CONFIG_PM_CLK=y +CONFIG_PM_DEVFREQ=y +CONFIG_PM_DEVFREQ_EVENT=y +CONFIG_PM_GENERIC_DOMAINS=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_PM_OPP=y +CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y +CONFIG_POWER_RESET=y +CONFIG_POWER_SUPPLY=y +CONFIG_POWER_SUPPLY_HWMON=y +CONFIG_PREEMPT=y +CONFIG_PREEMPTION=y +CONFIG_PREEMPT_BUILD=y +CONFIG_PREEMPT_COUNT=y +# CONFIG_PREEMPT_NONE is not set +CONFIG_PREEMPT_RCU=y +CONFIG_PRINTK_TIME=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_PROC_VMCORE=y +CONFIG_PTP_1588_CLOCK_OPTIONAL=y +CONFIG_PWM=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_PWM_SYSFS=y +# CONFIG_QFMT_V2 is not set +CONFIG_QUEUED_RWLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_QUOTA=y +CONFIG_QUOTACTL=y +CONFIG_RAID_ATTRS=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MODULE_REGION_FULL=y +CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y +CONFIG_RATIONAL=y +# CONFIG_RAVE_SP_CORE is not set +CONFIG_RCU_TRACE=y +CONFIG_REALTEK_PHY=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_SPI=y +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_ARM_SCMI is not set +CONFIG_REGULATOR_FAN53555=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_PWM=y +CONFIG_REGULATOR_RK808=y +CONFIG_RELOCATABLE=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_SCMI=y +CONFIG_RFS_ACCEL=y +CONFIG_ROCKCHIP_ERRATUM_3588001=y +CONFIG_ROCKCHIP_GRF=y +CONFIG_ROCKCHIP_IODOMAIN=y +CONFIG_ROCKCHIP_IOMMU=y +CONFIG_ROCKCHIP_MBOX=y +CONFIG_ROCKCHIP_PHY=y +CONFIG_ROCKCHIP_PM_DOMAINS=y +CONFIG_ROCKCHIP_THERMAL=y +CONFIG_ROCKCHIP_TIMER=y +CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +CONFIG_RPS=y +CONFIG_RSEQ=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_RK808=y +CONFIG_RTC_I2C_AND_SPI=y +CONFIG_RTC_NVMEM=y +# CONFIG_RUNTIME_TESTING_MENU is not set +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_SCHED_MC=y +CONFIG_SCSI=y +CONFIG_SCSI_COMMON=y +# CONFIG_SCSI_LOWLEVEL is not set +# CONFIG_SCSI_PROC_FS is not set +CONFIG_SCSI_SAS_ATTRS=y +CONFIG_SCSI_SAS_HOST_SMP=y +CONFIG_SCSI_SAS_LIBSAS=y +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SENSORS_ARM_SCMI is not set +CONFIG_SENSORS_ARM_SCPI=y +CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_8250_DWLIB=y +CONFIG_SERIAL_8250_EXAR=y +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_FSL=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_PCI=y +CONFIG_SERIAL_8250_PCILIB=y +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_SERIAL_MCTRL_GPIO=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIO=y +CONFIG_SERIO_AMBAKMI=y +CONFIG_SERIO_LIBPS2=y +CONFIG_SG_POOL=y +CONFIG_SLUB_DEBUG=y +CONFIG_SMP=y +CONFIG_SOCK_RX_QUEUE_MAPPING=y +CONFIG_SOFTIRQ_ON_OWN_STACK=y +CONFIG_SPARSEMEM=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSE_IRQ=y +CONFIG_SPI=y +CONFIG_SPI_BITBANG=y +CONFIG_SPI_DYNAMIC=y +CONFIG_SPI_MASTER=y +CONFIG_SPI_MEM=y +CONFIG_SPI_ROCKCHIP=y +CONFIG_SPI_ROCKCHIP_SFC=y +CONFIG_SPI_SPIDEV=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +# CONFIG_SQUASHFS_EMBEDDED is not set +CONFIG_SQUASHFS_FILE_CACHE=y +# CONFIG_SQUASHFS_FILE_DIRECT is not set +CONFIG_SRAM=y +CONFIG_STACKDEPOT=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_PER_TASK=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_STACKTRACE=y +# CONFIG_STAGING is not set +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_PLATFORM=y +CONFIG_STRICT_DEVMEM=y +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_SWAP is not set +CONFIG_SWIOTLB=y +CONFIG_SWPHY=y +CONFIG_SYNC_FILE=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_SYSFS_SYSCALL=y +CONFIG_SYSVIPC_COMPAT=y +# CONFIG_TEXTSEARCH is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_EMULATION=y +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_STEP_WISE=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THREAD_INFO_IN_TASK=y +CONFIG_TICK_CPU_ACCOUNTING=y +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_TRACE_CLOCK=y +CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y +# CONFIG_TRANSPARENT_HUGEPAGE_MADVISE is not set +CONFIG_TRANS_TABLE=y +CONFIG_TREE_RCU=y +CONFIG_TREE_SRCU=y +CONFIG_TYPEC=y +# CONFIG_TYPEC_ANX7411 is not set +CONFIG_TYPEC_FUSB302=y +# CONFIG_TYPEC_HD3SS3220 is not set +# CONFIG_TYPEC_MUX_FSA4480 is not set +# CONFIG_TYPEC_MUX_GPIO_SBU is not set +# CONFIG_TYPEC_MUX_NB7VPQ904M is not set +# CONFIG_TYPEC_MUX_PI3USB30532 is not set +# CONFIG_TYPEC_RT1719 is not set +# CONFIG_TYPEC_STUSB160X is not set +# CONFIG_TYPEC_TCPCI is not set +CONFIG_TYPEC_TCPM=y +# CONFIG_TYPEC_TPS6598X is not set +# CONFIG_TYPEC_WUSB3801 is not set +# CONFIG_UACCE is not set +# CONFIG_UCLAMP_TASK is not set +# CONFIG_UEVENT_HELPER is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_UNMAP_KERNEL_AT_EL0=y +CONFIG_USB=y +CONFIG_USB_COMMON=y +CONFIG_USB_DWC3=y +CONFIG_USB_DWC3_HOST=y +CONFIG_USB_DWC3_OF_SIMPLE=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_HID=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_PHY=y +CONFIG_USB_ROLE_SWITCH=y +CONFIG_USB_STORAGE=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_ULPI=y +CONFIG_USB_ULPI_BUS=y +CONFIG_USB_ULPI_VIEWPORT=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_PLATFORM=y +# CONFIG_VIRTIO_MENU is not set +CONFIG_VMAP_STACK=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_WATCHDOG_CORE=y +CONFIG_XARRAY_MULTI=y +CONFIG_XPS=y +CONFIG_XXHASH=y +CONFIG_XZ_DEC_ARM=y +CONFIG_XZ_DEC_ARMTHUMB=y +CONFIG_XZ_DEC_BCJ=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZONE_DMA32=y diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts index 2b5e300516..8c2e4daf79 100644 --- a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3568-photonicat.dts @@ -44,8 +44,8 @@ modem-rfkill { compatible = "rfkill-gpio"; - name = "modem-rfkill"; - type = "wwan"; + label = "modem-rfkill"; + radio-type = "wwan"; reset-gpios = <&gpio0 RK_PB0 GPIO_ACTIVE_LOW>; shutdown-gpios = <&gpio4 RK_PC4 GPIO_ACTIVE_HIGH>; }; diff --git a/lede/target/linux/rockchip/image/Makefile b/lede/target/linux/rockchip/image/Makefile index a2b711a436..7767a53a06 100644 --- a/lede/target/linux/rockchip/image/Makefile +++ b/lede/target/linux/rockchip/image/Makefile @@ -73,7 +73,7 @@ define Device/Default DEVICE_DTS = rockchip/$$(SOC)-$(lastword $(subst _, ,$(1))) endef -ifdef CONFIG_LINUX_6_1 +ifndef CONFIG_LINUX_5_15 DTS_CPPFLAGS += -DDTS_NO_LEGACY endif diff --git a/lede/target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch b/lede/target/linux/rockchip/patches-6.1/007-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch similarity index 100% rename from lede/target/linux/rockchip/patches-6.1/019-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch rename to lede/target/linux/rockchip/patches-6.1/007-v6.3-mmc-sdhci-of-dwcmshc-Update-DLL-and-pre.patch diff --git a/lede/target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch b/lede/target/linux/rockchip/patches-6.1/008-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch similarity index 100% rename from lede/target/linux/rockchip/patches-6.1/020-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch rename to lede/target/linux/rockchip/patches-6.1/008-v6.4-mmc-sdhci-of-dwcmshc-properly-determine.patch diff --git a/lede/target/linux/rockchip/patches-6.1/011-v6.3-net-rfkill-gpio-add-DT-support.patch b/lede/target/linux/rockchip/patches-6.1/011-v6.3-net-rfkill-gpio-add-DT-support.patch new file mode 100644 index 0000000000..15e7b7c22f --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.1/011-v6.3-net-rfkill-gpio-add-DT-support.patch @@ -0,0 +1,66 @@ +From d64c732dfc9edcd57feb693c23162117737e426b Mon Sep 17 00:00:00 2001 +From: Philipp Zabel +Date: Mon, 2 Jan 2023 18:29:34 +0100 +Subject: [PATCH] net: rfkill: gpio: add DT support + +Allow probing rfkill-gpio via device tree. This hooks up the already +existing support that was started in commit 262c91ee5e52 ("net: +rfkill: gpio: prepare for DT and ACPI support") via the "rfkill-gpio" +compatible, with the "name" and "type" properties renamed to "label" +and "radio-type", respectively, in the device tree case. + +Signed-off-by: Philipp Zabel +Link: https://lore.kernel.org/r/20230102-rfkill-gpio-dt-v2-2-d1b83758c16d@pengutronix.de +Signed-off-by: Johannes Berg +--- + net/rfkill/rfkill-gpio.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +--- a/net/rfkill/rfkill-gpio.c ++++ b/net/rfkill/rfkill-gpio.c +@@ -75,6 +75,8 @@ static int rfkill_gpio_probe(struct platform_device *pdev) + { + struct rfkill_gpio_data *rfkill; + struct gpio_desc *gpio; ++ const char *name_property; ++ const char *type_property; + const char *type_name; + int ret; + +@@ -82,8 +84,15 @@ static int rfkill_gpio_probe(struct platform_device *pdev) + if (!rfkill) + return -ENOMEM; + +- device_property_read_string(&pdev->dev, "name", &rfkill->name); +- device_property_read_string(&pdev->dev, "type", &type_name); ++ if (dev_of_node(&pdev->dev)) { ++ name_property = "label"; ++ type_property = "radio-type"; ++ } else { ++ name_property = "name"; ++ type_property = "type"; ++ } ++ device_property_read_string(&pdev->dev, name_property, &rfkill->name); ++ device_property_read_string(&pdev->dev, type_property, &type_name); + + if (!rfkill->name) + rfkill->name = dev_name(&pdev->dev); +@@ -157,12 +166,19 @@ static const struct acpi_device_id rfkill_acpi_match[] = { + MODULE_DEVICE_TABLE(acpi, rfkill_acpi_match); + #endif + ++static const struct of_device_id rfkill_of_match[] __maybe_unused = { ++ { .compatible = "rfkill-gpio", }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rfkill_of_match); ++ + static struct platform_driver rfkill_gpio_driver = { + .probe = rfkill_gpio_probe, + .remove = rfkill_gpio_remove, + .driver = { + .name = "rfkill_gpio", + .acpi_match_table = ACPI_PTR(rfkill_acpi_match), ++ .of_match_table = of_match_ptr(rfkill_of_match), + }, + }; diff --git a/lede/target/linux/rockchip/patches-6.1/012-v6.4-net-rfkill-gpio-Add-explicit-include-for-of.h.patch b/lede/target/linux/rockchip/patches-6.1/012-v6.4-net-rfkill-gpio-Add-explicit-include-for-of.h.patch new file mode 100644 index 0000000000..dbcafff9b5 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.1/012-v6.4-net-rfkill-gpio-Add-explicit-include-for-of.h.patch @@ -0,0 +1,29 @@ +From 75c7124ef3bafe0e9d1801d6449196dc3105df24 Mon Sep 17 00:00:00 2001 +From: Rob Herring +Date: Wed, 5 Apr 2023 15:27:17 -0500 +Subject: [PATCH] net: rfkill-gpio: Add explicit include for of.h + +With linux/acpi.h no longer implicitly including of.h, add an explicit +include of of.h to fix the following error: + +net/rfkill/rfkill-gpio.c:181:21: error: implicit declaration of function 'of_match_ptr' is invalid in C99 [-Werror,-Wimplicit-function-declaration] + +Acked-by: Johannes Berg +Reviewed-by: Jacob Keller +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Rob Herring +Signed-off-by: Rafael J. Wysocki +--- + net/rfkill/rfkill-gpio.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/rfkill/rfkill-gpio.c ++++ b/net/rfkill/rfkill-gpio.c +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + #include + #include + #include diff --git a/lede/target/linux/rockchip/patches-6.1/114-rfkill-gpio-add-of_match_table-support.patch b/lede/target/linux/rockchip/patches-6.1/114-rfkill-gpio-add-of_match_table-support.patch deleted file mode 100644 index 7b8a50ff46..0000000000 --- a/lede/target/linux/rockchip/patches-6.1/114-rfkill-gpio-add-of_match_table-support.patch +++ /dev/null @@ -1,34 +0,0 @@ -From b4aeb93e697e4dbe2d336d01290e92e98acfd83c Mon Sep 17 00:00:00 2001 -From: jensen -Date: Sat, 15 Oct 2022 18:47:24 +0800 -Subject: [PATCH] rfkill: gpio: add of_match_table support - -Signed-off-by: jensen ---- - net/rfkill/rfkill-gpio.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/net/rfkill/rfkill-gpio.c -+++ b/net/rfkill/rfkill-gpio.c -@@ -164,6 +164,13 @@ static const struct acpi_device_id rfkil - }; - MODULE_DEVICE_TABLE(acpi, rfkill_acpi_match); - #endif -+#ifdef CONFIG_OF -+static struct of_device_id rfkill_gpio_of_match[] = { -+ { .compatible = "rfkill-gpio" }, -+ { }, -+}; -+MODULE_DEVICE_TABLE(of, rfkill_gpio_of_match); -+#endif - - static struct platform_driver rfkill_gpio_driver = { - .probe = rfkill_gpio_probe, -@@ -171,6 +178,7 @@ static struct platform_driver rfkill_gpi - .driver = { - .name = "rfkill_gpio", - .acpi_match_table = ACPI_PTR(rfkill_acpi_match), -+ .of_match_table = of_match_ptr(rfkill_gpio_of_match), - }, - }; - diff --git a/lede/target/linux/rockchip/patches-6.6/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch b/lede/target/linux/rockchip/patches-6.6/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch new file mode 100644 index 0000000000..792028b292 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/005-arm64-dts-rockchip-add-EEPROM-node-for-NanoPi-R4S.patch @@ -0,0 +1,31 @@ +From af20b3384e8723077cc6484160b0cf4e9be321de Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 7 Jun 2021 15:45:37 +0800 +Subject: [PATCH] arm64: dts: rockchip: add EEPROM node for NanoPi R4S + +NanoPi R4S has a EEPROM attached to the 2nd I2C bus (U92), which +stores the MAC address. + +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -68,6 +68,15 @@ + status = "disabled"; + }; + ++&i2c2 { ++ eeprom@51 { ++ compatible = "microchip,24c02", "atmel,24c02"; ++ reg = <0x51>; ++ pagesize = <16>; ++ read-only; /* This holds our MAC */ ++ }; ++}; ++ + &i2c4 { + status = "disabled"; + }; diff --git a/lede/target/linux/rockchip/patches-6.6/101-net-realtek-r8169-add-LED-configuration-from-OF.patch b/lede/target/linux/rockchip/patches-6.6/101-net-realtek-r8169-add-LED-configuration-from-OF.patch new file mode 100644 index 0000000000..fba29fe9c7 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/101-net-realtek-r8169-add-LED-configuration-from-OF.patch @@ -0,0 +1,58 @@ +From edcc2833819f6750bf003b95a6ac856aced26274 Mon Sep 17 00:00:00 2001 +From: AnYun +Date: Sat, 18 Mar 2023 23:05:16 +0800 +Subject: [PATCH] r8169: add LED configuration from OF + +--- + drivers/net/ethernet/realtek/r8169_main.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/drivers/net/ethernet/realtek/r8169_main.c ++++ b/drivers/net/ethernet/realtek/r8169_main.c +@@ -17,6 +17,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -174,6 +175,7 @@ enum rtl_registers { + MAR0 = 8, /* Multicast filter. */ + CounterAddrLow = 0x10, + CounterAddrHigh = 0x14, ++ CustomLED = 0x18, + TxDescStartAddrLow = 0x20, + TxDescStartAddrHigh = 0x24, + TxHDescStartAddrLow = 0x28, +@@ -5202,6 +5204,22 @@ static bool rtl_aspm_is_safe(struct rtl8 + return false; + } + ++static int rtl_led_configuration(struct rtl8169_private *tp) ++{ ++ u32 led_data; ++ int ret; ++ ++ ret = of_property_read_u32(tp->pci_dev->dev.of_node, ++ "realtek,led-data", &led_data); ++ ++ if (ret) ++ return ret; ++ ++ RTL_W16(tp, CustomLED, led_data); ++ ++ return 0; ++} ++ + static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) + { + struct rtl8169_private *tp; +@@ -5373,6 +5391,7 @@ static int rtl_init_one(struct pci_dev * + if (!tp->counters) + return -ENOMEM; + ++ rtl_led_configuration(tp); + pci_set_drvdata(pdev, tp); + + rc = r8169_mdio_register(tp); diff --git a/lede/target/linux/rockchip/patches-6.6/102-net-phy-realtek-RTL8211-add-LED-configuration-from-OF.patch b/lede/target/linux/rockchip/patches-6.6/102-net-phy-realtek-RTL8211-add-LED-configuration-from-OF.patch new file mode 100644 index 0000000000..7a3ff4b8fb --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/102-net-phy-realtek-RTL8211-add-LED-configuration-from-OF.patch @@ -0,0 +1,44 @@ +From edcc2833819f6750bf003b95a6ac856aced26276 Mon Sep 17 00:00:00 2001 +From: AnYun +Date: Mon, 3 Apr 2023 23:26:04 +0800 +Subject: [PATCH] net: phy: realtek: add LED configuration from OF for 8211f + +--- + drivers/net/phy/realtek.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -28,6 +28,8 @@ + #define RTL821x_EXT_PAGE_SELECT 0x1e + #define RTL821x_PAGE_SELECT 0x1f + ++#define RTL8211F_LCR 0x10 ++#define RTL8211F_EEELCR 0x11 + #define RTL8211F_PHYCR1 0x18 + #define RTL8211F_PHYCR2 0x19 + #define RTL8211F_INSR 0x1d +@@ -357,6 +359,7 @@ static int rtl8211f_config_init(struct p + struct rtl821x_priv *priv = phydev->priv; + struct device *dev = &phydev->mdio.dev; + u16 val_txdly, val_rxdly; ++ u32 led_data; + int ret; + + ret = phy_modify_paged_changed(phydev, 0xa43, RTL8211F_PHYCR1, +@@ -423,6 +426,15 @@ static int rtl8211f_config_init(struct p + val_rxdly ? "enabled" : "disabled"); + } + ++ ret = of_property_read_u32(dev->of_node, ++ "realtek,led-data", &led_data); ++ if (!ret) { ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0xd04); ++ phy_write(phydev, RTL8211F_LCR, led_data); ++ phy_write(phydev, RTL8211F_EEELCR, 0x0); ++ phy_write(phydev, RTL821x_PAGE_SELECT, 0x0); ++ } ++ + if (priv->has_phycr2) { + ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2, + RTL8211F_CLKOUT_EN, priv->phycr2); diff --git a/lede/target/linux/rockchip/patches-6.6/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch b/lede/target/linux/rockchip/patches-6.6/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch new file mode 100644 index 0000000000..694ddefc45 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/103-arm64-rockchip-add-OF-node-for-USB-eth-on-NanoPi-R2S.patch @@ -0,0 +1,24 @@ +From 2795c8b31a686bdb8338f9404d18ef7a154f0d75 Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Sun, 26 Jul 2020 13:32:59 +0200 +Subject: [PATCH] arm64: rockchip: add OF node for USB eth on NanoPi R2S + +This adds the OF node for the USB3 ethernet adapter on the FriendlyARM +NanoPi R2S. Add the correct value for the RTL8153 LED configuration +register to match the blink behavior of the other port on the device. + +Signed-off-by: David Bauer +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 7 +++++++ + 1 file changed, 1 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -397,6 +397,7 @@ + rtl8153: device@2 { + compatible = "usbbda,8153"; + reg = <2>; ++ realtek,led-data = <0x87>; + }; + }; + diff --git a/lede/target/linux/rockchip/patches-6.6/105-nanopi-r4s-sd-signalling.patch b/lede/target/linux/rockchip/patches-6.6/105-nanopi-r4s-sd-signalling.patch new file mode 100644 index 0000000000..a04c14b70a --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/105-nanopi-r4s-sd-signalling.patch @@ -0,0 +1,26 @@ +From: David Bauer +Subject: arm64: dts: rockchip: disable UHS modes for NanoPi R4S + +The NanoPi R4S leaves the SD card in 1.8V signalling when rebooting +while U-Boot requires the card to be in 3.3V mode. + +Remove UHS support from the SD controller so the card remains in 3.3V +mode. This reduces transfer speeds but ensures a reboot whether from +userspace or following a kernel panic is always working. + +Signed-off-by: David Bauer + +--- a/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3399-nanopi-r4s.dts +@@ -121,6 +121,11 @@ + status = "disabled"; + }; + ++&sdmmc { ++ /delete-property/ sd-uhs-sdr104; ++ cap-sd-highspeed; ++}; ++ + &u2phy0_host { + phy-supply = <&vdd_5v>; + }; diff --git a/lede/target/linux/rockchip/patches-6.6/106-rockchip-rock-pi-4.patch b/lede/target/linux/rockchip/patches-6.6/106-rockchip-rock-pi-4.patch new file mode 100644 index 0000000000..3bdfe022f8 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/106-rockchip-rock-pi-4.patch @@ -0,0 +1,35 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -38,6 +38,8 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gr + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-dumo.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-inx.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-scarlet-kd.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-guangmiao-g4c.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-nanopi-r4se.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-hugsun-x99.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-khadas-edge-captain.dtb +@@ -59,6 +61,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ro + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-roc-pc-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-4c-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-4se.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4a.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4a-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4b.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-pi-4.dts +@@ -0,0 +1,13 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2019 Akash Gajjar ++ * Copyright (c) 2019 Pragnesh Patel ++ */ ++ ++/dts-v1/; ++#include "rk3399-rock-pi-4.dtsi" ++ ++/ { ++ model = "Radxa ROCK Pi 4"; ++ compatible = "radxa,rockpi4", "rockchip,rk3399"; ++}; diff --git a/lede/target/linux/rockchip/patches-6.6/107-mmc-core-set-initial-signal-voltage-on-power-off.patch b/lede/target/linux/rockchip/patches-6.6/107-mmc-core-set-initial-signal-voltage-on-power-off.patch new file mode 100644 index 0000000000..0a58265be2 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/107-mmc-core-set-initial-signal-voltage-on-power-off.patch @@ -0,0 +1,35 @@ +From 0d329112c709d6cfedf0fffb19f0cc6b19043f6b Mon Sep 17 00:00:00 2001 +From: Jonas Karlman +Date: Wed, 20 Feb 2019 07:38:34 +0000 +Subject: [PATCH] mmc: core: set initial signal voltage on power off + +Some boards have SD card connectors where the power rail cannot be switched +off by the driver. If the card has not been power cycled, it may still be +using 1.8V signaling after a warm re-boot. Bootroms expecting 3.3V signaling +will fail to boot from a UHS card that continue to use 1.8V signaling. + +Set initial signal voltage in mmc_power_off() to allow re-boot to function. + +This fixes re-boot with UHS cards on Asus Tinker Board (Rockchip RK3288), +same issue have been seen on some Rockchip RK3399 boards. + +I am sending this as a RFC because I have no insights into SD/MMC subsystem, +this change fix a re-boot issue on my boards and does not break emmc/sdio. +Is this an acceptable workaround? Any advice is appreciated. + +Signed-off-by: Jonas Karlman +--- + drivers/mmc/core/core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -1370,6 +1370,8 @@ void mmc_power_off(struct mmc_host *host + + mmc_pwrseq_power_off(host); + ++ mmc_set_initial_signal_voltage(host); ++ + host->ios.clock = 0; + host->ios.vdd = 0; + diff --git a/lede/target/linux/rockchip/patches-6.6/110-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch b/lede/target/linux/rockchip/patches-6.6/110-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch new file mode 100644 index 0000000000..5e2109292a --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/110-arm64-rk3568-update-gicv3-its-and-pci-msi-map.patch @@ -0,0 +1,77 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -64,7 +64,7 @@ + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x10 0x1f>; + clocks = <&cru ACLK_PCIE30X1_MST>, <&cru ACLK_PCIE30X1_SLV>, + <&cru ACLK_PCIE30X1_DBI>, <&cru PCLK_PCIE30X1>, + <&cru CLK_PCIE30X1_AUX_NDFT>; +@@ -87,7 +87,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; +- msi-map = <0x0 &gic 0x1000 0x1000>; ++ msi-map = <0x1000 &its 0x1000 0x1000>; + num-lanes = <1>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; +@@ -117,7 +117,7 @@ + compatible = "rockchip,rk3568-pcie"; + #address-cells = <3>; + #size-cells = <2>; +- bus-range = <0x0 0xf>; ++ bus-range = <0x20 0x2f>; + clocks = <&cru ACLK_PCIE30X2_MST>, <&cru ACLK_PCIE30X2_SLV>, + <&cru ACLK_PCIE30X2_DBI>, <&cru PCLK_PCIE30X2>, + <&cru CLK_PCIE30X2_AUX_NDFT>; +@@ -140,7 +140,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <3>; +- msi-map = <0x0 &gic 0x2000 0x1000>; ++ msi-map = <0x2000 &its 0x2000 0x1000>; + num-lanes = <2>; + phys = <&pcie30phy>; + phy-names = "pcie-phy"; +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -315,14 +315,21 @@ + + gic: interrupt-controller@fd400000 { + compatible = "arm,gic-v3"; ++ #interrupt-cells = <3>; ++ #address-cells = <2>; ++ #size-cells = <2>; ++ ranges; ++ interrupt-controller; ++ + reg = <0x0 0xfd400000 0 0x10000>, /* GICD */ +- <0x0 0xfd460000 0 0x80000>; /* GICR */ ++ <0x0 0xfd460000 0 0xc0000>; /* GICR */ + interrupts = ; +- interrupt-controller; +- #interrupt-cells = <3>; +- mbi-alias = <0x0 0xfd410000>; +- mbi-ranges = <296 24>; +- msi-controller; ++ its: interrupt-controller@fd440000 { ++ compatible = "arm,gic-v3-its"; ++ msi-controller; ++ #msi-cells = <1>; ++ reg = <0x0 0xfd440000 0x0 0x20000>; ++ }; + }; + + usb_host0_ehci: usb@fd800000 { +@@ -988,7 +995,7 @@ + num-ib-windows = <6>; + num-ob-windows = <2>; + max-link-speed = <2>; +- msi-map = <0x0 &gic 0x0 0x1000>; ++ msi-map = <0x0 &its 0x0 0x1000>; + num-lanes = <1>; + phys = <&combphy2 PHY_TYPE_PCIE>; + phy-names = "pcie-phy"; diff --git a/lede/target/linux/rockchip/patches-6.6/111-irqchip-gic-v3-add-hackaround-for-rk3568-its.patch b/lede/target/linux/rockchip/patches-6.6/111-irqchip-gic-v3-add-hackaround-for-rk3568-its.patch new file mode 100644 index 0000000000..f12735b073 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/111-irqchip-gic-v3-add-hackaround-for-rk3568-its.patch @@ -0,0 +1,31 @@ +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -4757,11 +4757,13 @@ static bool __maybe_unused its_enable_qu + return true; + } + +-static bool __maybe_unused its_enable_rk3588001(void *data) ++static bool __maybe_unused its_enable_rk35xx(void *data) + { + struct its_node *its = data; + +- if (!of_machine_is_compatible("rockchip,rk3588") && ++ if (!of_machine_is_compatible("rockchip,rk3566") && ++ !of_machine_is_compatible("rockchip,rk3568") && ++ !of_machine_is_compatible("rockchip,rk3588") && + !of_machine_is_compatible("rockchip,rk3588s")) + return false; + +@@ -4827,10 +4829,10 @@ static const struct gic_quirk its_quirks + #endif + #ifdef CONFIG_ROCKCHIP_ERRATUM_3588001 + { +- .desc = "ITS: Rockchip erratum RK3588001", ++ .desc = "ITS: Rockchip erratum RK35XX", + .iidr = 0x0201743b, + .mask = 0xffffffff, +- .init = its_enable_rk3588001, ++ .init = its_enable_rk35xx, + }, + #endif + { diff --git a/lede/target/linux/rockchip/patches-6.6/112-arm64-dts-rockchip-rk3568-Add-xpcs-support.patch b/lede/target/linux/rockchip/patches-6.6/112-arm64-dts-rockchip-rk3568-Add-xpcs-support.patch new file mode 100644 index 0000000000..3741303acb --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/112-arm64-dts-rockchip-rk3568-Add-xpcs-support.patch @@ -0,0 +1,33 @@ +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -175,11 +175,13 @@ + clocks = <&cru SCLK_GMAC0>, <&cru SCLK_GMAC0_RX_TX>, + <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_MAC0_REFOUT>, + <&cru ACLK_GMAC0>, <&cru PCLK_GMAC0>, +- <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>; ++ <&cru SCLK_GMAC0_RX_TX>, <&cru CLK_GMAC0_PTP_REF>, ++ <&cru PCLK_XPCS>; + clock-names = "stmmaceth", "mac_clk_rx", + "mac_clk_tx", "clk_mac_refout", + "aclk_mac", "pclk_mac", +- "clk_mac_speed", "ptp_ref"; ++ "clk_mac_speed", "ptp_ref", ++ "pclk_xpcs"; + resets = <&cru SRST_A_GMAC0>; + reset-names = "stmmaceth"; + rockchip,grf = <&grf>; +--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi +@@ -376,6 +376,12 @@ + status = "disabled"; + }; + ++ xpcs: syscon@fda00000 { ++ compatible = "rockchip,rk3568-xpcs", "syscon"; ++ reg = <0x0 0xfda00000 0x0 0x200000>; ++ status = "disabled"; ++ }; ++ + pmugrf: syscon@fdc20000 { + compatible = "rockchip,rk3568-pmugrf", "syscon", "simple-mfd"; + reg = <0x0 0xfdc20000 0x0 0x10000>; diff --git a/lede/target/linux/rockchip/patches-6.6/113-ethernet-stmicro-stmmac-Add-SGMII-QSGMII-support.patch b/lede/target/linux/rockchip/patches-6.6/113-ethernet-stmicro-stmmac-Add-SGMII-QSGMII-support.patch new file mode 100644 index 0000000000..ac646edc1d --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/113-ethernet-stmicro-stmmac-Add-SGMII-QSGMII-support.patch @@ -0,0 +1,320 @@ +From ca89ea7e0760c096c6fd807d321ecb8416f8cd9d Mon Sep 17 00:00:00 2001 +From: David Wu +Date: Thu, 31 Dec 2020 18:32:03 +0800 +Subject: [PATCH] ethernet: stmicro: stmmac: Add SGMII/QSGMII support for + RK3568 + +After the completion of Clause 37 auto-negotiation, xpcs automatically +switches to the negotiated speed for 10/100/1000M. + +Change-Id: Iab9dd6ee61a35bf89fd3a0721f5d398de501a7ec +Signed-off-by: David Wu +--- + .../net/ethernet/stmicro/stmmac/dwmac-rk.c | 228 +++++++++++++++++- + 1 file changed, 217 insertions(+), 11 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -30,6 +31,8 @@ struct rk_gmac_ops { + void (*set_to_rgmii)(struct rk_priv_data *bsp_priv, + int tx_delay, int rx_delay); + void (*set_to_rmii)(struct rk_priv_data *bsp_priv); ++ void (*set_to_sgmii)(struct rk_priv_data *bsp_priv); ++ void (*set_to_qsgmii)(struct rk_priv_data *bsp_priv); + void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed); + void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed); + void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input, +@@ -40,7 +43,7 @@ struct rk_gmac_ops { + }; + + static const char * const rk_clocks[] = { +- "aclk_mac", "pclk_mac", "mac_clk_tx", "clk_mac_speed", ++ "aclk_mac", "pclk_mac", "pclk_xpcs", "mac_clk_tx", "clk_mac_speed", + }; + + static const char * const rk_rmii_clocks[] = { +@@ -50,6 +53,7 @@ static const char * const rk_rmii_clocks + enum rk_clocks_index { + RK_ACLK_MAC = 0, + RK_PCLK_MAC, ++ RK_PCLK_XPCS, + RK_MAC_CLK_TX, + RK_CLK_MAC_SPEED, + RK_MAC_CLK_RX, +@@ -81,6 +85,7 @@ struct rk_priv_data { + + struct regmap *grf; + struct regmap *php_grf; ++ struct regmap *xpcs; + }; + + #define HIWORD_UPDATE(val, mask, shift) \ +@@ -93,6 +98,128 @@ struct rk_priv_data { + (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ + ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) + ++/* XPCS */ ++#define XPCS_APB_INCREMENT (0x4) ++#define XPCS_APB_MASK GENMASK_ULL(20, 0) ++ ++#define SR_MII_BASE (0x1F0000) ++#define SR_MII1_BASE (0x1A0000) ++ ++#define VR_MII_DIG_CTRL1 (0x8000) ++#define VR_MII_AN_CTRL (0x8001) ++#define VR_MII_AN_INTR_STS (0x8002) ++#define VR_MII_LINK_TIMER_CTRL (0x800A) ++ ++#define SR_MII_CTRL_AN_ENABLE \ ++ (BMCR_ANENABLE | BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000) ++#define MII_MAC_AUTO_SW (0x0200) ++#define PCS_MODE_OFFSET (0x1) ++#define MII_AN_INTR_EN (0x1) ++#define PCS_SGMII_MODE (0x2 << PCS_MODE_OFFSET) ++#define PCS_QSGMII_MODE (0X3 << PCS_MODE_OFFSET) ++#define VR_MII_CTRL_SGMII_AN_EN (PCS_SGMII_MODE | MII_AN_INTR_EN) ++#define VR_MII_CTRL_QSGMII_AN_EN (PCS_QSGMII_MODE | MII_AN_INTR_EN) ++ ++#define SR_MII_OFFSET(_x) ({ \ ++ typeof(_x) (x) = (_x); \ ++ (((x) == 0) ? SR_MII_BASE : (SR_MII1_BASE + ((x) - 1) * 0x10000)); \ ++}) \ ++ ++static int xpcs_read(void *priv, int reg) ++{ ++ struct rk_priv_data *bsp_priv = (struct rk_priv_data *)priv; ++ int ret, val; ++ ++ ret = regmap_read(bsp_priv->xpcs, ++ (u32)(reg * XPCS_APB_INCREMENT) & XPCS_APB_MASK, ++ &val); ++ if (ret) ++ return ret; ++ ++ return val; ++} ++ ++static int xpcs_write(void *priv, int reg, u16 value) ++{ ++ struct rk_priv_data *bsp_priv = (struct rk_priv_data *)priv; ++ ++ return regmap_write(bsp_priv->xpcs, ++ (reg * XPCS_APB_INCREMENT) & XPCS_APB_MASK, value); ++} ++ ++static int xpcs_poll_reset(struct rk_priv_data *bsp_priv, int dev) ++{ ++ /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ ++ unsigned int retries = 12; ++ int ret; ++ ++ do { ++ msleep(50); ++ ret = xpcs_read(bsp_priv, SR_MII_OFFSET(dev) + MDIO_CTRL1); ++ if (ret < 0) ++ return ret; ++ } while (ret & MDIO_CTRL1_RESET && --retries); ++ ++ return (ret & MDIO_CTRL1_RESET) ? -ETIMEDOUT : 0; ++} ++ ++static int xpcs_soft_reset(struct rk_priv_data *bsp_priv, int dev) ++{ ++ int ret; ++ ++ ret = xpcs_write(bsp_priv, SR_MII_OFFSET(dev) + MDIO_CTRL1, ++ MDIO_CTRL1_RESET); ++ if (ret < 0) ++ return ret; ++ ++ return xpcs_poll_reset(bsp_priv, dev); ++} ++ ++static int xpcs_setup(struct rk_priv_data *bsp_priv, int mode) ++{ ++ int ret, i, idx = bsp_priv->id; ++ u32 val; ++ ++ if (mode == PHY_INTERFACE_MODE_QSGMII && idx > 0) ++ return 0; ++ ++ ret = xpcs_soft_reset(bsp_priv, idx); ++ if (ret) { ++ dev_err(&bsp_priv->pdev->dev, "xpcs_soft_reset fail %d\n", ret); ++ return ret; ++ } ++ ++ xpcs_write(bsp_priv, SR_MII_OFFSET(0) + VR_MII_AN_INTR_STS, 0x0); ++ xpcs_write(bsp_priv, SR_MII_OFFSET(0) + VR_MII_LINK_TIMER_CTRL, 0x1); ++ ++ if (mode == PHY_INTERFACE_MODE_SGMII) ++ xpcs_write(bsp_priv, SR_MII_OFFSET(0) + VR_MII_AN_CTRL, ++ VR_MII_CTRL_SGMII_AN_EN); ++ else ++ xpcs_write(bsp_priv, SR_MII_OFFSET(0) + VR_MII_AN_CTRL, ++ VR_MII_CTRL_QSGMII_AN_EN); ++ ++ if (mode == PHY_INTERFACE_MODE_QSGMII) { ++ for (i = 0; i < 4; i++) { ++ val = xpcs_read(bsp_priv, ++ SR_MII_OFFSET(i) + VR_MII_DIG_CTRL1); ++ xpcs_write(bsp_priv, ++ SR_MII_OFFSET(i) + VR_MII_DIG_CTRL1, ++ val | MII_MAC_AUTO_SW); ++ xpcs_write(bsp_priv, SR_MII_OFFSET(i) + MII_BMCR, ++ SR_MII_CTRL_AN_ENABLE); ++ } ++ } else { ++ val = xpcs_read(bsp_priv, SR_MII_OFFSET(idx) + VR_MII_DIG_CTRL1); ++ xpcs_write(bsp_priv, SR_MII_OFFSET(idx) + VR_MII_DIG_CTRL1, ++ val | MII_MAC_AUTO_SW); ++ xpcs_write(bsp_priv, SR_MII_OFFSET(idx) + MII_BMCR, ++ SR_MII_CTRL_AN_ENABLE); ++ } ++ ++ return ret; ++} ++ + #define PX30_GRF_GMAC_CON1 0x0904 + + /* PX30_GRF_GMAC_CON1 */ +@@ -1021,6 +1148,7 @@ static const struct rk_gmac_ops rk3399_o + #define RK3568_GRF_GMAC1_CON1 0x038c + + /* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */ ++#define RK3568_GMAC_GMII_MODE GRF_BIT(7) + #define RK3568_GMAC_PHY_INTF_SEL_RGMII \ + (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6)) + #define RK3568_GMAC_PHY_INTF_SEL_RMII \ +@@ -1036,6 +1164,46 @@ static const struct rk_gmac_ops rk3399_o + #define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8) + #define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) + ++#define RK3568_PIPE_GRF_XPCS_CON0 0X0040 ++ ++#define RK3568_PIPE_GRF_XPCS_QGMII_MAC_SEL GRF_BIT(0) ++#define RK3568_PIPE_GRF_XPCS_SGMII_MAC_SEL GRF_BIT(1) ++#define RK3568_PIPE_GRF_XPCS_PHY_READY GRF_BIT(2) ++ ++static void rk3568_set_to_sgmii(struct rk_priv_data *bsp_priv) ++{ ++ struct device *dev = &bsp_priv->pdev->dev; ++ u32 con1; ++ ++ if (IS_ERR(bsp_priv->grf)) { ++ dev_err(dev, "Missing rockchip,grf property\n"); ++ return; ++ } ++ ++ con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 : ++ RK3568_GRF_GMAC0_CON1; ++ regmap_write(bsp_priv->grf, con1, RK3568_GMAC_GMII_MODE); ++ ++ xpcs_setup(bsp_priv, PHY_INTERFACE_MODE_SGMII); ++} ++ ++static void rk3568_set_to_qsgmii(struct rk_priv_data *bsp_priv) ++{ ++ struct device *dev = &bsp_priv->pdev->dev; ++ u32 con1; ++ ++ if (IS_ERR(bsp_priv->grf)) { ++ dev_err(dev, "Missing rockchip,grf property\n"); ++ return; ++ } ++ ++ con1 = (bsp_priv->id == 1) ? RK3568_GRF_GMAC1_CON1 : ++ RK3568_GRF_GMAC0_CON1; ++ regmap_write(bsp_priv->grf, con1, RK3568_GMAC_GMII_MODE); ++ ++ xpcs_setup(bsp_priv, PHY_INTERFACE_MODE_QSGMII); ++} ++ + static void rk3568_set_to_rgmii(struct rk_priv_data *bsp_priv, + int tx_delay, int rx_delay) + { +@@ -1108,6 +1276,8 @@ static void rk3568_set_gmac_speed(struct + static const struct rk_gmac_ops rk3568_ops = { + .set_to_rgmii = rk3568_set_to_rgmii, + .set_to_rmii = rk3568_set_to_rmii, ++ .set_to_sgmii = rk3568_set_to_sgmii, ++ .set_to_qsgmii = rk3568_set_to_qsgmii, + .set_rgmii_speed = rk3568_set_gmac_speed, + .set_rmii_speed = rk3568_set_gmac_speed, + .regs_valid = true, +@@ -1580,7 +1750,7 @@ static int gmac_clk_enable(struct rk_pri + return 0; + } + +-static int phy_power_on(struct rk_priv_data *bsp_priv, bool enable) ++static int rk_gmac_phy_power_on(struct rk_priv_data *bsp_priv, bool enable) + { + struct regulator *ldo = bsp_priv->regulator; + int ret; +@@ -1679,6 +1849,18 @@ static struct rk_priv_data *rk_gmac_setu + "rockchip,grf"); + bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node, + "rockchip,php-grf"); ++ bsp_priv->xpcs = syscon_regmap_lookup_by_phandle(dev->of_node, ++ "rockchip,xpcs"); ++ if (!IS_ERR(bsp_priv->xpcs)) { ++ struct phy *comphy; ++ ++ comphy = devm_of_phy_get(&pdev->dev, dev->of_node, NULL); ++ if (IS_ERR(comphy)) ++ dev_err(dev, "devm_of_phy_get error\n"); ++ ret = phy_init(comphy); ++ if (ret) ++ dev_err(dev, "phy_init error\n"); ++ } + + if (plat->phy_node) { + bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node, +@@ -1756,11 +1938,19 @@ static int rk_gmac_powerup(struct rk_pri + dev_info(dev, "init for RMII\n"); + bsp_priv->ops->set_to_rmii(bsp_priv); + break; ++ case PHY_INTERFACE_MODE_SGMII: ++ dev_info(dev, "init for SGMII\n"); ++ bsp_priv->ops->set_to_sgmii(bsp_priv); ++ break; ++ case PHY_INTERFACE_MODE_QSGMII: ++ dev_info(dev, "init for QSGMII\n"); ++ bsp_priv->ops->set_to_qsgmii(bsp_priv); ++ break; + default: + dev_err(dev, "NO interface defined!\n"); + } + +- ret = phy_power_on(bsp_priv, true); ++ ret = rk_gmac_phy_power_on(bsp_priv, true); + if (ret) { + gmac_clk_enable(bsp_priv, false); + return ret; +@@ -1781,7 +1971,7 @@ static void rk_gmac_powerdown(struct rk_ + + pm_runtime_put_sync(&gmac->pdev->dev); + +- phy_power_on(gmac, false); ++ rk_gmac_phy_power_on(gmac, false); + gmac_clk_enable(gmac, false); + } + +@@ -1802,6 +1992,9 @@ static void rk_fix_speed(void *priv, uns + if (bsp_priv->ops->set_rmii_speed) + bsp_priv->ops->set_rmii_speed(bsp_priv, speed); + break; ++ case PHY_INTERFACE_MODE_SGMII: ++ case PHY_INTERFACE_MODE_QSGMII: ++ break; + default: + dev_err(dev, "unsupported interface %d", bsp_priv->phy_iface); + } diff --git a/lede/target/linux/rockchip/patches-6.6/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch b/lede/target/linux/rockchip/patches-6.6/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch new file mode 100644 index 0000000000..856906550f --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/201-rockchip-rk3328-add-i2c0-controller-for-nanopi-r2s.patch @@ -0,0 +1,22 @@ +From 3b7eb946b1d640d684a921e53e1e50985ab7eb89 Mon Sep 17 00:00:00 2001 +From: QiuSimons <45143996+QiuSimons@users.noreply.github.com> +Date: Tue, 4 Aug 2020 20:17:53 +0800 +Subject: [PATCH] rockchip: rk3328: add i2c0 controller for nanopi r2s + +--- + arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts | 4 ++++ + 1 files changed, 4 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -166,6 +166,10 @@ + }; + }; + ++&i2c0 { ++ status = "okay"; ++}; ++ + &i2c1 { + status = "okay"; + diff --git a/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch b/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch new file mode 100644 index 0000000000..ea311951be --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/205-rockchip-rk3328-add-support-for-FriendlyARM-NanoPi-Neo3.patch @@ -0,0 +1,442 @@ +From 0f989817a4c1d2c3d196d550ff05cda98bc91324 Mon Sep 17 00:00:00 2001 +From: Julian Pidancet +Date: Sun, 23 Jan 2022 16:34:08 +0100 +Subject: [PATCH v2] rockchip: rk3328: add support for FriendlyARM NanoPi NEO3 + +This patch adds support for FriendlyARM NanoPi NEO3 + +Soc: RockChip RK3328 +RAM: 1GB/2GB DDR4 +LAN: 10/100/1000M Ethernet with unique MAC +USB Host: 1x USB3.0 Type A and 2x USB2.0 on 2.54mm pin header +MicroSD: x 1 for system boot and storage +LED: Power LED x 1, System LED x 1 +Key: User Button x 1 +Fan: 2 Pin JST ZH 1.5mm Connector for 5V Fan +GPIO: 26 pin-header, include I2C, UART, SPI, I2S, GPIO +Power: 5V/1A, via Type-C or GPIO + +Signed-off-by: Julian Pidancet +--- + +This is another shot at previous work submitted by Marty Jones + (https://lore.kernel.org/linux-arm-kernel/20201228152836.02795e09.mj8263788@gmail.com/), +which is now a year old. + +v2: Following up on Robin Murphy's comments, the NEO3 DTS is now +standalone and no longer includes the nanopi R2S one. The lan_led and +wan_len nodes have been removed, and the sys_led node has been renamed +to status_led in accordance with the board schematics. + + arch/arm64/boot/dts/rockchip/Makefile | 1 + + .../boot/dts/rockchip/rk3328-nanopi-neo3.dts | 396 ++++++++++++++++++ + 2 files changed, 397 insertions(+) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts + +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -17,6 +17,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-ev + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2c-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-neo3.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-orangepi-r1-plus-lts.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-rock64.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-neo3.dts +@@ -0,0 +1,394 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++/* ++ * Copyright (c) 2020 David Bauer ++ * Copyright (c) 2022 Julian Pidancet ++ */ ++ ++/dts-v1/; ++ ++#include ++#include ++#include "rk3328.dtsi" ++ ++/ { ++ model = "FriendlyElec NanoPi NEO3"; ++ compatible = "friendlyarm,nanopi-neo3", "rockchip,rk3328"; ++ ++ aliases { ++ led-boot = &status_led; ++ led-failsafe = &status_led; ++ led-running = &status_led; ++ led-upgrade = &status_led; ++ }; ++ ++ chosen { ++ stdout-path = "serial2:1500000n8"; ++ }; ++ ++ gmac_clk: gmac-clock { ++ compatible = "fixed-clock"; ++ clock-frequency = <125000000>; ++ clock-output-names = "gmac_clkin"; ++ #clock-cells = <0>; ++ }; ++ ++ keys { ++ compatible = "gpio-keys"; ++ pinctrl-0 = <&reset_button_pin>; ++ pinctrl-names = "default"; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ debounce-interval = <50>; ++ }; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ pinctrl-0 = <&status_led_pin>; ++ pinctrl-names = "default"; ++ ++ status_led: led-0 { ++ gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>; ++ label = "nanopi-neo3:green:status"; ++ }; ++ }; ++ ++ vcc_io_sdio: sdmmcio-regulator { ++ compatible = "regulator-gpio"; ++ enable-active-high; ++ gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>; ++ pinctrl-0 = <&sdio_vcc_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_io_sdio"; ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-settling-time-us = <5000>; ++ regulator-type = "voltage"; ++ startup-delay-us = <2000>; ++ states = <1800000 0x1>, ++ <3300000 0x0>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vcc_sd: sdmmc-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>; ++ pinctrl-0 = <&sdmmc0m1_pin>; ++ pinctrl-names = "default"; ++ regulator-name = "vcc_sd"; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <&vcc_io_33>; ++ }; ++ ++ vdd_5v: vdd-5v { ++ compatible = "regulator-fixed"; ++ regulator-name = "vdd_5v"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ }; ++ ++ vcc_rtl8153: vcc-rtl8153-regulator { ++ compatible = "regulator-fixed"; ++ gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rtl8153_en_drv>; ++ regulator-always-on; ++ regulator-name = "vcc_rtl8153"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ enable-active-high; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu1 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu2 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&cpu3 { ++ cpu-supply = <&vdd_arm>; ++}; ++ ++&display_subsystem { ++ status = "disabled"; ++}; ++ ++&gmac2io { ++ assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>; ++ assigned-clock-parents = <&gmac_clk>, <&gmac_clk>; ++ clock_in_out = "input"; ++ phy-handle = <&rtl8211e>; ++ phy-mode = "rgmii"; ++ phy-supply = <&vcc_io_33>; ++ pinctrl-0 = <&rgmiim1_pins>; ++ pinctrl-names = "default"; ++ rx_delay = <0x18>; ++ snps,aal; ++ tx_delay = <0x24>; ++ status = "okay"; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ rtl8211e: ethernet-phy@1 { ++ reg = <1>; ++ pinctrl-0 = <ð_phy_reset_pin>; ++ pinctrl-names = "default"; ++ reset-assert-us = <10000>; ++ reset-deassert-us = <50000>; ++ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>; ++ }; ++ }; ++}; ++ ++&i2c1 { ++ status = "okay"; ++ ++ rk805: pmic@18 { ++ compatible = "rockchip,rk805"; ++ reg = <0x18>; ++ interrupt-parent = <&gpio1>; ++ interrupts = <24 IRQ_TYPE_LEVEL_LOW>; ++ #clock-cells = <1>; ++ clock-output-names = "xin32k", "rk805-clkout2"; ++ gpio-controller; ++ #gpio-cells = <2>; ++ pinctrl-0 = <&pmic_int_l>; ++ pinctrl-names = "default"; ++ rockchip,system-power-controller; ++ wakeup-source; ++ ++ vcc1-supply = <&vdd_5v>; ++ vcc2-supply = <&vdd_5v>; ++ vcc3-supply = <&vdd_5v>; ++ vcc4-supply = <&vdd_5v>; ++ vcc5-supply = <&vcc_io_33>; ++ vcc6-supply = <&vdd_5v>; ++ ++ regulators { ++ vdd_log: DCDC_REG1 { ++ regulator-name = "vdd_log"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ ++ vdd_arm: DCDC_REG2 { ++ regulator-name = "vdd_arm"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <712500>; ++ regulator-max-microvolt = <1450000>; ++ regulator-ramp-delay = <12500>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <950000>; ++ }; ++ }; ++ ++ vcc_ddr: DCDC_REG3 { ++ regulator-name = "vcc_ddr"; ++ regulator-always-on; ++ regulator-boot-on; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ }; ++ }; ++ ++ vcc_io_33: DCDC_REG4 { ++ regulator-name = "vcc_io_33"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <3300000>; ++ }; ++ }; ++ ++ vcc_18: LDO_REG1 { ++ regulator-name = "vcc_18"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vcc18_emmc: LDO_REG2 { ++ regulator-name = "vcc18_emmc"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1800000>; ++ }; ++ }; ++ ++ vdd_10: LDO_REG3 { ++ regulator-name = "vdd_10"; ++ regulator-always-on; ++ regulator-boot-on; ++ regulator-min-microvolt = <1000000>; ++ regulator-max-microvolt = <1000000>; ++ ++ regulator-state-mem { ++ regulator-on-in-suspend; ++ regulator-suspend-microvolt = <1000000>; ++ }; ++ }; ++ }; ++ }; ++}; ++ ++&io_domains { ++ pmuio-supply = <&vcc_io_33>; ++ vccio1-supply = <&vcc_io_33>; ++ vccio2-supply = <&vcc18_emmc>; ++ vccio3-supply = <&vcc_io_sdio>; ++ vccio4-supply = <&vcc_18>; ++ vccio5-supply = <&vcc_io_33>; ++ vccio6-supply = <&vcc_io_33>; ++ status = "okay"; ++}; ++ ++&pinctrl { ++ button { ++ reset_button_pin: reset-button-pin { ++ rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ ethernet-phy { ++ eth_phy_reset_pin: eth-phy-reset-pin { ++ rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>; ++ }; ++ }; ++ ++ leds { ++ status_led_pin: status-led-pin { ++ rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++ ++ pmic { ++ pmic_int_l: pmic-int-l { ++ rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ sd { ++ sdio_vcc_pin: sdio-vcc-pin { ++ rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>; ++ }; ++ }; ++ ++ usb { ++ rtl8153_en_drv: rtl8153-en-drv { ++ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>; ++ }; ++ }; ++}; ++ ++&pwm2 { ++ status = "okay"; ++}; ++ ++&sdmmc { ++ bus-width = <4>; ++ cap-sd-highspeed; ++ disable-wp; ++ pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>; ++ pinctrl-names = "default"; ++ sd-uhs-sdr12; ++ sd-uhs-sdr25; ++ sd-uhs-sdr50; ++ sd-uhs-sdr104; ++ vmmc-supply = <&vcc_sd>; ++ vqmmc-supply = <&vcc_io_sdio>; ++ status = "okay"; ++}; ++ ++&tsadc { ++ rockchip,hw-tshut-mode = <0>; ++ rockchip,hw-tshut-polarity = <0>; ++ status = "okay"; ++}; ++ ++&u2phy { ++ status = "okay"; ++}; ++ ++&u2phy_host { ++ status = "okay"; ++}; ++ ++&u2phy_otg { ++ status = "okay"; ++}; ++ ++&uart2 { ++ status = "okay"; ++}; ++ ++&usb20_otg { ++ status = "okay"; ++ dr_mode = "host"; ++}; ++ ++&usb_host0_ehci { ++ status = "okay"; ++}; ++ ++&usb_host0_ohci { ++ status = "okay"; ++}; ++ ++&usbdrd3 { ++ dr_mode = "host"; ++ status = "okay"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ usb-eth@2 { ++ compatible = "realtek,rtl8153"; ++ reg = <2>; ++ ++ realtek,led-data = <0x87>; ++ }; ++}; diff --git a/lede/target/linux/rockchip/patches-6.6/210-rockchip-rk356x-add-support-for-new-boards.patch b/lede/target/linux/rockchip/patches-6.6/210-rockchip-rk356x-add-support-for-new-boards.patch new file mode 100644 index 0000000000..699e7f5b9b --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/210-rockchip-rk356x-add-support-for-new-boards.patch @@ -0,0 +1,30 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -81,6 +81,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-an + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.1.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-panther-x2.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-radxa-cm3-io.dtb +@@ -98,9 +99,19 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-lu + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5c.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-nanopi-r5s.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-opc-h66k.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-opc-h68k.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-opc-h69k.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r66s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-r68s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-t68m.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-radxa-e25.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-roc-pc.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-photonicat.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-seewo-sv21.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mrkaio-m68s.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-mrkaio-m68s-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6a-io.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-edgeble-neu6b-io.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588-evb1-v10.dtb diff --git a/lede/target/linux/rockchip/patches-6.6/211-rockchip-rk3399-add-support-more-devices.patch b/lede/target/linux/rockchip/patches-6.6/211-rockchip-rk3399-add-support-more-devices.patch new file mode 100644 index 0000000000..3765f3d69e --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/211-rockchip-rk3399-add-support-more-devices.patch @@ -0,0 +1,14 @@ +--- a/arch/arm64/boot/dts/rockchip/Makefile ++++ b/arch/arm64/boot/dts/rockchip/Makefile +@@ -68,6 +68,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-ro + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4b.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4b-plus.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock-pi-4c.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-king3399.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-h3399pc.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-dlfr100.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-mpc1903.dtb ++dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-xiaobao-nas-v1.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rock960.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64-v2.dtb + dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-rockpro64.dtb diff --git a/lede/target/linux/rockchip/patches-6.6/801-char-add-support-for-rockchip-hardware-random-number.patch b/lede/target/linux/rockchip/patches-6.6/801-char-add-support-for-rockchip-hardware-random-number.patch new file mode 100644 index 0000000000..9d35a5925d --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/801-char-add-support-for-rockchip-hardware-random-number.patch @@ -0,0 +1,45 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] char: add support for rockchip hardware random number + generator + +This patch provides hardware random number generator support for all rockchip SOC. + +rockchip-rng.c from https://github.com/rockchip-linux/kernel/blob/develop-4.4/drivers/char/hw_random/rockchip-rng.c + +Signed-off-by: wevsty +--- + +--- a/drivers/char/hw_random/Kconfig ++++ b/drivers/char/hw_random/Kconfig +@@ -383,6 +383,19 @@ config HW_RANDOM_STM32 + + If unsure, say N. + ++config HW_RANDOM_ROCKCHIP ++ tristate "Rockchip Random Number Generator support" ++ depends on ARCH_ROCKCHIP ++ default HW_RANDOM ++ help ++ This driver provides kernel-side support for the Random Number ++ Generator hardware found on Rockchip cpus. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called rockchip-rng. ++ ++ If unsure, say Y. ++ + config HW_RANDOM_PIC32 + tristate "Microchip PIC32 Random Number Generator support" + depends on MACH_PIC32 || COMPILE_TEST +--- a/drivers/char/hw_random/Makefile ++++ b/drivers/char/hw_random/Makefile +@@ -35,6 +35,7 @@ obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += + obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o + obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o + obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o ++obj-$(CONFIG_HW_RANDOM_ROCKCHIP) += rockchip-rng.o + obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o + obj-$(CONFIG_HW_RANDOM_MESON) += meson-rng.o + obj-$(CONFIG_HW_RANDOM_CAVIUM) += cavium-rng.o cavium-rng-vf.o diff --git a/lede/target/linux/rockchip/patches-6.6/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch b/lede/target/linux/rockchip/patches-6.6/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch new file mode 100644 index 0000000000..6667b33e54 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/802-arm64-dts-rockchip-add-hardware-random-number-genera.patch @@ -0,0 +1,69 @@ +From e5b5361651940ff5c0c1784dfd0130abec7ab535 Mon Sep 17 00:00:00 2001 +From: wevsty +Date: Mon, 24 Aug 2020 02:27:11 +0800 +Subject: [PATCH] arm64: dts: rockchip: add hardware random number generator + for RK3328 and RK3399 + +Adding Hardware Random Number Generator Resources to the RK3328 and RK3399. + +Signed-off-by: wevsty +--- + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -281,6 +281,17 @@ + status = "disabled"; + }; + ++ rng: rng@ff060000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff060000 0x0 0x4000>; ++ ++ clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO>, <&cru HCLK_CRYPTO_SLV>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "disabled"; ++ }; ++ + grf: syscon@ff100000 { + compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd"; + reg = <0x0 0xff100000 0x0 0x1000>; +--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi +@@ -2106,6 +2106,16 @@ + }; + }; + ++ rng: rng@ff8b8000 { ++ compatible = "rockchip,cryptov1-rng"; ++ reg = <0x0 0xff8b8000 0x0 0x1000>; ++ clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ clock-names = "clk_crypto", "hclk_crypto"; ++ assigned-clocks = <&cru SCLK_CRYPTO1>, <&cru HCLK_S_CRYPTO1>; ++ assigned-clock-rates = <150000000>, <100000000>; ++ status = "okay"; ++ }; ++ + gpu: gpu@ff9a0000 { + compatible = "rockchip,rk3399-mali", "arm,mali-t860"; + reg = <0x0 0xff9a0000 0x0 0x10000>; +--- a/arch/arm64/boot/dts/rockchip/rk3568.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3568.dtsi +@@ -215,6 +215,16 @@ + }; + }; + ++ rng: rng@fe388000 { ++ compatible = "rockchip,cryptov2-rng"; ++ reg = <0x0 0xfe388000 0x0 0x2000>; ++ clocks = <&cru CLK_TRNG_NS>, <&cru HCLK_TRNG_NS>; ++ clock-names = "clk_trng", "hclk_trng"; ++ resets = <&cru SRST_TRNG_NS>; ++ reset-names = "reset"; ++ status = "disabled"; ++ }; ++ + combphy0: phy@fe820000 { + compatible = "rockchip,rk3568-naneng-combphy"; + reg = <0x0 0xfe820000 0x0 0x100>; diff --git a/lede/target/linux/rockchip/patches-6.6/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch b/lede/target/linux/rockchip/patches-6.6/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch new file mode 100644 index 0000000000..6d19871742 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/803-PM-devfreq-rockchip-add-devfreq-driver-for-rk3328-dmc.patch @@ -0,0 +1,44 @@ +From fcd9629c05f373771e85920e1c1d0ab252617878 Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 13:53:25 +0800 +Subject: [PATCH] PM / devfreq: rockchip: add devfreq driver for rk3328 dmc + +Signed-off-by: hmz007 +--- + drivers/devfreq/Kconfig | 18 +- + drivers/devfreq/Makefile | 1 + + drivers/devfreq/rk3328_dmc.c | 846 +++++++++++++++++++++++++++++++++++ + 3 files changed, 862 insertions(+), 3 deletions(-) + create mode 100644 drivers/devfreq/rk3328_dmc.c + +--- a/drivers/devfreq/Kconfig ++++ b/drivers/devfreq/Kconfig +@@ -129,6 +129,18 @@ config ARM_MEDIATEK_CCI_DEVFREQ + buck voltages and update a proper CCI frequency. Use the notification + to get the regulator status. + ++config ARM_RK3328_DMC_DEVFREQ ++ tristate "ARM RK3328 DMC DEVFREQ Driver" ++ depends on ARCH_ROCKCHIP ++ select DEVFREQ_EVENT_ROCKCHIP_DFI ++ select DEVFREQ_GOV_SIMPLE_ONDEMAND ++ select PM_DEVFREQ_EVENT ++ select PM_OPP ++ help ++ This adds the DEVFREQ driver for the RK3328 DMC(Dynamic Memory Controller). ++ It sets the frequency for the memory controller and reads the usage counts ++ from hardware. ++ + config ARM_RK3399_DMC_DEVFREQ + tristate "ARM RK3399 DMC DEVFREQ Driver" + depends on (ARCH_ROCKCHIP && HAVE_ARM_SMCCC) || \ +--- a/drivers/devfreq/Makefile ++++ b/drivers/devfreq/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += + obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx-bus.o + obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o + obj-$(CONFIG_ARM_MEDIATEK_CCI_DEVFREQ) += mtk-cci-devfreq.o ++obj-$(CONFIG_ARM_RK3328_DMC_DEVFREQ) += rk3328_dmc.o + obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o + obj-$(CONFIG_ARM_SUN8I_A33_MBUS_DEVFREQ) += sun8i-a33-mbus.o + obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o diff --git a/lede/target/linux/rockchip/patches-6.6/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch b/lede/target/linux/rockchip/patches-6.6/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch new file mode 100644 index 0000000000..74b76af622 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/804-clk-rockchip-support-setting-ddr-clock-via-SIP-Version-2-.patch @@ -0,0 +1,210 @@ +From ce6d3614888e6358466f0e84e248177a6bca5258 Mon Sep 17 00:00:00 2001 +From: Tang Yun ping +Date: Thu, 4 May 2017 20:49:58 +0800 +Subject: [PATCH] clk: rockchip: support setting ddr clock via SIP Version 2 + APIs + +commit 764e893ee82321938fc6f4349e9e7caf06a04410 rockchip. + +Signed-off-by: Tang Yun ping +Signed-off-by: hmz007 +--- + drivers/clk/rockchip/clk-ddr.c | 130 ++++++++++++++++++++++++++++ + drivers/clk/rockchip/clk-rk3328.c | 7 +- + drivers/clk/rockchip/clk.h | 3 +- + include/soc/rockchip/rockchip_sip.h | 11 +++ + 4 files changed, 147 insertions(+), 4 deletions(-) + +--- a/drivers/clk/rockchip/clk-ddr.c ++++ b/drivers/clk/rockchip/clk-ddr.c +@@ -87,6 +87,133 @@ static const struct clk_ops rockchip_ddr + .get_parent = rockchip_ddrclk_get_parent, + }; + ++/* See v4.4/include/dt-bindings/display/rk_fb.h */ ++#define SCREEN_NULL 0 ++#define SCREEN_HDMI 6 ++ ++static inline int rk_drm_get_lcdc_type(void) ++{ ++ return SCREEN_NULL; ++} ++ ++struct share_params { ++ u32 hz; ++ u32 lcdc_type; ++ u32 vop; ++ u32 vop_dclk_mode; ++ u32 sr_idle_en; ++ u32 addr_mcu_el3; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag1; ++ /* ++ * 1: need to wait flag1 ++ * 0: never wait flag1 ++ */ ++ u32 wait_flag0; ++ u32 complt_hwirq; ++ /* if need, add parameter after */ ++}; ++ ++struct rockchip_ddrclk_data { ++ u32 inited_flag; ++ void __iomem *share_memory; ++}; ++ ++static struct rockchip_ddrclk_data ddr_data; ++ ++static void rockchip_ddrclk_data_init(void) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_SHARE_MEM, ++ 1, SHARE_PAGE_TYPE_DDR, 0, ++ 0, 0, 0, 0, &res); ++ ++ if (!res.a0) { ++ ddr_data.share_memory = (void __iomem *)ioremap(res.a1, 1<<12); ++ ddr_data.inited_flag = 1; ++ } ++} ++ ++static int rockchip_ddrclk_sip_set_rate_v2(struct clk_hw *hw, ++ unsigned long drate, ++ unsigned long prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = drate; ++ p->lcdc_type = rk_drm_get_lcdc_type(); ++ p->wait_flag1 = 1; ++ p->wait_flag0 = 1; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_SET_RATE, ++ 0, 0, 0, 0, &res); ++ ++ if ((int)res.a1 == -6) { ++ pr_err("%s: timeout, drate = %lumhz\n", __func__, drate/1000000); ++ /* TODO: rockchip_dmcfreq_wait_complete(); */ ++ } ++ ++ return res.a0; ++} ++ ++static unsigned long rockchip_ddrclk_sip_recalc_rate_v2 ++ (struct clk_hw *hw, unsigned long parent_rate) ++{ ++ struct arm_smccc_res res; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_GET_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static long rockchip_ddrclk_sip_round_rate_v2(struct clk_hw *hw, ++ unsigned long rate, ++ unsigned long *prate) ++{ ++ struct share_params *p; ++ struct arm_smccc_res res; ++ ++ if (!ddr_data.inited_flag) ++ rockchip_ddrclk_data_init(); ++ ++ p = (struct share_params *)ddr_data.share_memory; ++ ++ p->hz = rate; ++ ++ arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, ++ SHARE_PAGE_TYPE_DDR, 0, ++ ROCKCHIP_SIP_CONFIG_DRAM_ROUND_RATE, ++ 0, 0, 0, 0, &res); ++ if (!res.a0) ++ return res.a1; ++ else ++ return 0; ++} ++ ++static const struct clk_ops rockchip_ddrclk_sip_ops_v2 = { ++ .recalc_rate = rockchip_ddrclk_sip_recalc_rate_v2, ++ .set_rate = rockchip_ddrclk_sip_set_rate_v2, ++ .round_rate = rockchip_ddrclk_sip_round_rate_v2, ++ .get_parent = rockchip_ddrclk_get_parent, ++}; ++ + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, + u8 num_parents, int mux_offset, +@@ -114,6 +241,9 @@ struct clk *rockchip_clk_register_ddrclk + case ROCKCHIP_DDRCLK_SIP: + init.ops = &rockchip_ddrclk_sip_ops; + break; ++ case ROCKCHIP_DDRCLK_SIP_V2: ++ init.ops = &rockchip_ddrclk_sip_ops_v2; ++ break; + default: + pr_err("%s: unsupported ddrclk type %d\n", __func__, ddr_flag); + kfree(ddrclk); +--- a/drivers/clk/rockchip/clk-rk3328.c ++++ b/drivers/clk/rockchip/clk-rk3328.c +@@ -315,9 +315,10 @@ static struct rockchip_clk_branch rk3328 + RK3328_CLKGATE_CON(14), 1, GFLAGS), + + /* PD_DDR */ +- COMPOSITE(0, "clk_ddr", mux_ddrphy_p, CLK_IGNORE_UNUSED, +- RK3328_CLKSEL_CON(3), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, +- RK3328_CLKGATE_CON(0), 4, GFLAGS), ++ COMPOSITE_DDRCLK(SCLK_DDRCLK, "sclk_ddrc", mux_ddrphy_p, 0, ++ RK3328_CLKSEL_CON(3), 8, 2, 0, 3, ++ ROCKCHIP_DDRCLK_SIP_V2), ++ + GATE(0, "clk_ddrmsch", "clk_ddr", CLK_IGNORE_UNUSED, + RK3328_CLKGATE_CON(18), 6, GFLAGS), + GATE(0, "clk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, +--- a/drivers/clk/rockchip/clk.h ++++ b/drivers/clk/rockchip/clk.h +@@ -486,7 +486,8 @@ struct clk *rockchip_clk_register_mmc(co + * DDRCLK flags, including method of setting the rate + * ROCKCHIP_DDRCLK_SIP: use SIP call to bl31 to change ddrclk rate. + */ +-#define ROCKCHIP_DDRCLK_SIP BIT(0) ++#define ROCKCHIP_DDRCLK_SIP 0x01 ++#define ROCKCHIP_DDRCLK_SIP_V2 0x03 + + struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, + const char *const *parent_names, +--- a/include/soc/rockchip/rockchip_sip.h ++++ b/include/soc/rockchip/rockchip_sip.h +@@ -16,5 +16,16 @@ + #define ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ 0x06 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM 0x07 + #define ROCKCHIP_SIP_CONFIG_DRAM_SET_ODT_PD 0x08 ++#define ROCKCHIP_SIP_CONFIG_DRAM_GET_VERSION 0x08 ++ ++#define ROCKCHIP_SIP_SHARE_MEM 0x82000009 ++ ++/* Share mem page types */ ++typedef enum { ++ SHARE_PAGE_TYPE_INVALID = 0, ++ SHARE_PAGE_TYPE_UARTDBG, ++ SHARE_PAGE_TYPE_DDR, ++ SHARE_PAGE_TYPE_MAX, ++} share_page_type_t; + + #endif diff --git a/lede/target/linux/rockchip/patches-6.6/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch b/lede/target/linux/rockchip/patches-6.6/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch new file mode 100644 index 0000000000..9b5437cd8b --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/805-PM-devfreq-rockchip-dfi-add-more-soc-support.patch @@ -0,0 +1,660 @@ +From 4db93c6dad0c71750b86163df2fdb21c35f00d9a Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 12:49:48 +0800 +Subject: [PATCH] PM / devfreq: rockchip-dfi: add more soc support + +Signed-off-by: hmz007 +--- + drivers/devfreq/event/rockchip-dfi.c | 554 ++++++++++++++++++++++++--- + 1 file changed, 505 insertions(+), 49 deletions(-) + +--- a/drivers/devfreq/event/rockchip-dfi.c ++++ b/drivers/devfreq/event/rockchip-dfi.c +@@ -18,25 +18,66 @@ + #include + #include + +-#include +- +-#define RK3399_DMC_NUM_CH 2 ++#define PX30_PMUGRF_OS_REG2 0x208 + ++#define RK3128_GRF_SOC_CON0 0x140 ++#define RK3128_GRF_OS_REG1 0x1cc ++#define RK3128_GRF_DFI_WRNUM 0x220 ++#define RK3128_GRF_DFI_RDNUM 0x224 ++#define RK3128_GRF_DFI_TIMERVAL 0x22c ++#define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6)) ++#define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6)) ++ ++#define RK3288_PMU_SYS_REG2 0x9c ++#define RK3288_GRF_SOC_CON4 0x254 ++#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4) ++#define RK3288_DFI_EN (0x30003 << 14) ++#define RK3288_DFI_DIS (0x30000 << 14) ++#define RK3288_LPDDR_SEL (0x10001 << 13) ++#define RK3288_DDR3_SEL (0x10000 << 13) ++ ++#define RK3328_GRF_OS_REG2 0x5d0 ++ ++#define RK3368_GRF_DDRC0_CON0 0x600 ++#define RK3368_GRF_SOC_STATUS5 0x494 ++#define RK3368_GRF_SOC_STATUS6 0x498 ++#define RK3368_GRF_SOC_STATUS8 0x4a0 ++#define RK3368_GRF_SOC_STATUS9 0x4a4 ++#define RK3368_GRF_SOC_STATUS10 0x4a8 ++#define RK3368_DFI_EN (0x30003 << 5) ++#define RK3368_DFI_DIS (0x30000 << 5) ++ ++#define MAX_DMC_NUM_CH 2 ++#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7) ++#define READ_CH_INFO(n) (((n) >> 28) & 0x3) + /* DDRMON_CTRL */ +-#define DDRMON_CTRL 0x04 +-#define CLR_DDRMON_CTRL (0x1f0000 << 0) +-#define LPDDR4_EN (0x10001 << 4) +-#define HARDWARE_EN (0x10001 << 3) +-#define LPDDR3_EN (0x10001 << 2) +-#define SOFTWARE_EN (0x10001 << 1) +-#define SOFTWARE_DIS (0x10000 << 1) +-#define TIME_CNT_EN (0x10001 << 0) ++#define DDRMON_CTRL 0x04 ++#define CLR_DDRMON_CTRL (0x3f0000 << 0) ++#define DDR4_EN (0x10001 << 5) ++#define LPDDR4_EN (0x10001 << 4) ++#define HARDWARE_EN (0x10001 << 3) ++#define LPDDR2_3_EN (0x10001 << 2) ++#define SOFTWARE_EN (0x10001 << 1) ++#define SOFTWARE_DIS (0x10000 << 1) ++#define TIME_CNT_EN (0x10001 << 0) + + #define DDRMON_CH0_COUNT_NUM 0x28 + #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c + #define DDRMON_CH1_COUNT_NUM 0x3c + #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 + ++/* pmu grf */ ++#define PMUGRF_OS_REG2 0x308 ++ ++enum { ++ DDR4 = 0, ++ DDR3 = 3, ++ LPDDR2 = 5, ++ LPDDR3 = 6, ++ LPDDR4 = 7, ++ UNUSED = 0xFF ++}; ++ + struct dmc_usage { + u32 access; + u32 total; +@@ -50,33 +91,261 @@ struct dmc_usage { + struct rockchip_dfi { + struct devfreq_event_dev *edev; + struct devfreq_event_desc *desc; +- struct dmc_usage ch_usage[RK3399_DMC_NUM_CH]; ++ struct dmc_usage ch_usage[MAX_DMC_NUM_CH]; + struct device *dev; + void __iomem *regs; + struct regmap *regmap_pmu; ++ struct regmap *regmap_grf; ++ struct regmap *regmap_pmugrf; + struct clk *clk; ++ u32 dram_type; ++ /* ++ * available mask, 1: available, 0: not available ++ * each bit represent a channel ++ */ ++ u32 ch_msk; ++}; ++ ++static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_EN); ++} ++ ++static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, ++ RK3128_GRF_SOC_CON0, ++ RK3128_DDR_MONITOR_DISB); ++} ++ ++static int rk3128_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3128_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3128_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi_wr, dfi_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3128_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd); ++ regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer); ++ ++ edata->load_count = (dfi_wr + dfi_rd) * 4; ++ edata->total_count = dfi_timer; ++ ++ rk3128_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3128_dfi_ops = { ++ .disable = rk3128_dfi_disable, ++ .enable = rk3128_dfi_enable, ++ .get_event = rk3128_dfi_get_event, ++ .set_event = rk3128_dfi_set_event, ++}; ++ ++static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN); ++} ++ ++static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS); ++} ++ ++static int rk3288_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3288_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ u32 tmp, max = 0; ++ u32 i, busier_ch = 0; ++ u32 rd_count, wr_count, total_count; ++ ++ rk3288_dfi_stop_hardware_counter(edev); ++ ++ /* Find out which channel is busier */ ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count); ++ regmap_read(info->regmap_grf, ++ RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count); ++ info->ch_usage[i].access = (wr_count + rd_count) * 4; ++ info->ch_usage[i].total = total_count; ++ tmp = info->ch_usage[i].access; ++ if (tmp > max) { ++ busier_ch = i; ++ max = tmp; ++ } ++ } ++ rk3288_dfi_start_hardware_counter(edev); ++ ++ return busier_ch; ++} ++ ++static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ int busier_ch; ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ busier_ch = rk3288_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); ++ ++ edata->load_count = info->ch_usage[busier_ch].access; ++ edata->total_count = info->ch_usage[busier_ch].total; ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3288_dfi_ops = { ++ .disable = rk3288_dfi_disable, ++ .enable = rk3288_dfi_enable, ++ .get_event = rk3288_dfi_get_event, ++ .set_event = rk3288_dfi_set_event, ++}; ++ ++static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN); ++} ++ ++static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ ++ regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS); ++} ++ ++static int rk3368_dfi_disable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_enable(struct devfreq_event_dev *edev) ++{ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ return 0; ++} ++ ++static int rk3368_dfi_set_event(struct devfreq_event_dev *edev) ++{ ++ return 0; ++} ++ ++static int rk3368_dfi_get_event(struct devfreq_event_dev *edev, ++ struct devfreq_event_data *edata) ++{ ++ struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); ++ unsigned long flags; ++ u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer; ++ ++ local_irq_save(flags); ++ ++ rk3368_dfi_stop_hardware_counter(edev); ++ ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd); ++ regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer); ++ ++ edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 2; ++ edata->total_count = dfi_timer; ++ ++ rk3368_dfi_start_hardware_counter(edev); ++ ++ local_irq_restore(flags); ++ ++ return 0; ++} ++ ++static const struct devfreq_event_ops rk3368_dfi_ops = { ++ .disable = rk3368_dfi_disable, ++ .enable = rk3368_dfi_enable, ++ .get_event = rk3368_dfi_get_event, ++ .set_event = rk3368_dfi_set_event, + }; + + static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev) + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + void __iomem *dfi_regs = info->regs; +- u32 val; +- u32 ddr_type; +- +- /* get ddr type */ +- regmap_read(info->regmap_pmu, RK3399_PMUGRF_OS_REG2, &val); +- ddr_type = (val >> RK3399_PMUGRF_DDRTYPE_SHIFT) & +- RK3399_PMUGRF_DDRTYPE_MASK; + + /* clear DDRMON_CTRL setting */ + writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL); + + /* set ddr type to dfi */ +- if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR3) +- writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL); +- else if (ddr_type == RK3399_PMUGRF_DDRTYPE_LPDDR4) ++ if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) ++ writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == LPDDR4) + writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL); ++ else if (info->dram_type == DDR4) ++ writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL); + + /* enable count, use software mode */ + writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL); +@@ -100,12 +369,22 @@ static int rockchip_dfi_get_busier_ch(st + rockchip_dfi_stop_hardware_counter(edev); + + /* Find out which channel is busier */ +- for (i = 0; i < RK3399_DMC_NUM_CH; i++) { +- info->ch_usage[i].access = readl_relaxed(dfi_regs + +- DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4; ++ for (i = 0; i < MAX_DMC_NUM_CH; i++) { ++ if (!(info->ch_msk & BIT(i))) ++ continue; ++ + info->ch_usage[i].total = readl_relaxed(dfi_regs + + DDRMON_CH0_COUNT_NUM + i * 20); +- tmp = info->ch_usage[i].access; ++ ++ /* LPDDR4 BL = 16,other DDR type BL = 8 */ ++ tmp = readl_relaxed(dfi_regs + ++ DDRMON_CH0_DFI_ACCESS_NUM + i * 20); ++ if (info->dram_type == LPDDR4) ++ tmp *= 8; ++ else ++ tmp *= 4; ++ info->ch_usage[i].access = tmp; ++ + if (tmp > max) { + busier_ch = i; + max = tmp; +@@ -121,7 +400,8 @@ static int rockchip_dfi_disable(struct d + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + rockchip_dfi_stop_hardware_counter(edev); +- clk_disable_unprepare(info->clk); ++ if (info->clk) ++ clk_disable_unprepare(info->clk); + + return 0; + } +@@ -131,10 +411,13 @@ static int rockchip_dfi_enable(struct de + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int ret; + +- ret = clk_prepare_enable(info->clk); +- if (ret) { +- dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret); +- return ret; ++ if (info->clk) { ++ ret = clk_prepare_enable(info->clk); ++ if (ret) { ++ dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ++ ret); ++ return ret; ++ } + } + + rockchip_dfi_start_hardware_counter(edev); +@@ -151,8 +434,11 @@ static int rockchip_dfi_get_event(struct + { + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int busier_ch; ++ unsigned long flags; + ++ local_irq_save(flags); + busier_ch = rockchip_dfi_get_busier_ch(edev); ++ local_irq_restore(flags); + + edata->load_count = info->ch_usage[busier_ch].access; + edata->total_count = info->ch_usage[busier_ch].total; +@@ -167,22 +453,116 @@ static const struct devfreq_event_ops ro + .set_event = rockchip_dfi_set_event, + }; + +-static const struct of_device_id rockchip_dfi_id_match[] = { +- { .compatible = "rockchip,rk3399-dfi" }, +- { }, +-}; +-MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++static __init int px30_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; + +-static int rockchip_dfi_probe(struct platform_device *pdev) ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,pmugrf", 0); ++ if (node) { ++ data->regmap_pmugrf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmugrf)) ++ return PTR_ERR(data->regmap_pmugrf); ++ } ++ ++ regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3128_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) + { +- struct device *dev = &pdev->dev; +- struct rockchip_dfi *data; +- struct devfreq_event_desc *desc; + struct device_node *np = pdev->dev.of_node, *node; + +- data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); +- if (!data) +- return -ENOMEM; ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ desc->ops = &rk3128_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3288_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; ++ ++ node = of_parse_phandle(np, "rockchip,pmu", 0); ++ if (node) { ++ data->regmap_pmu = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_pmu)) ++ return PTR_ERR(data->regmap_pmu); ++ } ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ if (data->dram_type == DDR3) ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_DDR3_SEL); ++ else ++ regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, ++ RK3288_LPDDR_SEL); ++ ++ desc->ops = &rk3288_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3368_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ ++ if (!dev->parent || !dev->parent->of_node) ++ return -EINVAL; ++ ++ data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ ++ desc->ops = &rk3368_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rockchip_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device *dev = &pdev->dev; ++ struct device_node *np = pdev->dev.of_node, *node; ++ u32 val; + + data->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(data->regs)) +@@ -202,21 +582,95 @@ static int rockchip_dfi_probe(struct pla + if (IS_ERR(data->regmap_pmu)) + return PTR_ERR(data->regmap_pmu); + +- data->dev = dev; ++ regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = READ_CH_INFO(val); ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static __init int rk3328_dfi_init(struct platform_device *pdev, ++ struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc) ++{ ++ struct device_node *np = pdev->dev.of_node, *node; ++ struct resource *res; ++ u32 val; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ data->regs = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(data->regs)) ++ return PTR_ERR(data->regs); ++ ++ node = of_parse_phandle(np, "rockchip,grf", 0); ++ if (node) { ++ data->regmap_grf = syscon_node_to_regmap(node); ++ if (IS_ERR(data->regmap_grf)) ++ return PTR_ERR(data->regmap_grf); ++ } ++ ++ regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val); ++ data->dram_type = READ_DRAMTYPE_INFO(val); ++ data->ch_msk = 1; ++ data->clk = NULL; ++ ++ desc->ops = &rockchip_dfi_ops; ++ ++ return 0; ++} ++ ++static const struct of_device_id rockchip_dfi_id_match[] = { ++ { .compatible = "rockchip,px30-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init }, ++ { .compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init }, ++ { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, ++ { .compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init }, ++ { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init }, ++ { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init }, ++ { }, ++}; ++MODULE_DEVICE_TABLE(of, rockchip_dfi_id_match); ++ ++static int rockchip_dfi_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct rockchip_dfi *data; ++ struct devfreq_event_desc *desc; ++ struct device_node *np = pdev->dev.of_node; ++ const struct of_device_id *match; ++ int (*init)(struct platform_device *pdev, struct rockchip_dfi *data, ++ struct devfreq_event_desc *desc); ++ ++ data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + +- desc->ops = &rockchip_dfi_ops; ++ match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node); ++ if (match) { ++ init = match->data; ++ if (init) { ++ if (init(pdev, data, desc)) ++ return -EINVAL; ++ } else { ++ return 0; ++ } ++ } else { ++ return 0; ++ } + desc->driver_data = data; + desc->name = np->name; + data->desc = desc; ++ data->dev = dev; + +- data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc); ++ data->edev = devm_devfreq_event_add_edev(dev, desc); + if (IS_ERR(data->edev)) { +- dev_err(&pdev->dev, +- "failed to add devfreq-event device\n"); ++ dev_err(dev, "failed to add devfreq-event device\n"); + return PTR_ERR(data->edev); + } + diff --git a/lede/target/linux/rockchip/patches-6.6/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch b/lede/target/linux/rockchip/patches-6.6/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch new file mode 100644 index 0000000000..86d046133b --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/806-arm64-dts-rockchip-rk3328-add-dfi-node.patch @@ -0,0 +1,27 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: rockchip: rk3328: add dfi node + +Signed-off-by: hmz007 +[adjusted commit title] +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 7 +++++++ + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -1025,6 +1025,13 @@ + status = "disabled"; + }; + ++ dfi: dfi@ff790000 { ++ reg = <0x00 0xff790000 0x00 0x400>; ++ compatible = "rockchip,rk3328-dfi"; ++ rockchip,grf = <&grf>; ++ status = "disabled"; ++ }; ++ + gic: interrupt-controller@ff811000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; diff --git a/lede/target/linux/rockchip/patches-6.6/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch b/lede/target/linux/rockchip/patches-6.6/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch new file mode 100644 index 0000000000..15ca783a49 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/807-arm64-dts-nanopi-r2s-add-rk3328-dmc-relate-node.patch @@ -0,0 +1,126 @@ +From f9ae6e992d3d9e80357fee7d65ba0fe2dd37ae1f Mon Sep 17 00:00:00 2001 +From: hmz007 +Date: Tue, 19 Nov 2019 14:21:51 +0800 +Subject: [PATCH] arm64: dts: nanopi-r2: add rk3328-dmc relate node + +Signed-off-by: hmz007 +--- + .../rockchip/rk3328-dram-default-timing.dtsi | 311 ++++++++++++++++++ + .../dts/rockchip/rk3328-nanopi-r2-common.dtsi | 85 ++++- + include/dt-bindings/clock/rockchip-ddr.h | 63 ++++ + include/dt-bindings/memory/rk3328-dram.h | 159 +++++++++ + 4 files changed, 617 insertions(+), 1 deletion(-) + create mode 100644 arch/arm64/boot/dts/rockchip/rk3328-dram-default-timing.dtsi + create mode 100644 include/dt-bindings/clock/rockchip-ddr.h + create mode 100644 include/dt-bindings/memory/rk3328-dram.h + +--- a/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts ++++ b/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s.dts +@@ -7,6 +7,7 @@ + + #include + #include ++#include "rk3328-dram-default-timing.dtsi" + #include "rk3328.dtsi" + + / { +@@ -114,6 +115,72 @@ + regulator-boot-on; + vin-supply = <&vdd_5v>; + }; ++ ++ dmc: dmc { ++ compatible = "rockchip,rk3328-dmc"; ++ devfreq-events = <&dfi>; ++ center-supply = <&vdd_log>; ++ clocks = <&cru SCLK_DDRCLK>; ++ clock-names = "dmc_clk"; ++ operating-points-v2 = <&dmc_opp_table>; ++ ddr_timing = <&ddr_timing>; ++ upthreshold = <40>; ++ downdifferential = <20>; ++ auto-min-freq = <786000>; ++ auto-freq-en = <0>; ++ #cooling-cells = <2>; ++ status = "okay"; ++ ++ ddr_power_model: ddr_power_model { ++ compatible = "ddr_power_model"; ++ dynamic-power-coefficient = <120>; ++ static-power-coefficient = <200>; ++ ts = <32000 4700 (-80) 2>; ++ thermal-zone = "soc-thermal"; ++ }; ++ }; ++ ++ dmc_opp_table: dmc-opp-table { ++ compatible = "operating-points-v2"; ++ ++ rockchip,leakage-voltage-sel = < ++ 1 10 0 ++ 11 254 1 ++ >; ++ nvmem-cells = <&logic_leakage>; ++ nvmem-cell-names = "ddr_leakage"; ++ ++ opp-786000000 { ++ opp-hz = /bits/ 64 <786000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-798000000 { ++ opp-hz = /bits/ 64 <798000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-840000000 { ++ opp-hz = /bits/ 64 <840000000>; ++ opp-microvolt = <1075000>; ++ opp-microvolt-L0 = <1075000>; ++ opp-microvolt-L1 = <1050000>; ++ }; ++ opp-924000000 { ++ opp-hz = /bits/ 64 <924000000>; ++ opp-microvolt = <1100000>; ++ opp-microvolt-L0 = <1100000>; ++ opp-microvolt-L1 = <1075000>; ++ }; ++ opp-1056000000 { ++ opp-hz = /bits/ 64 <1056000000>; ++ opp-microvolt = <1175000>; ++ opp-microvolt-L0 = <1175000>; ++ opp-microvolt-L1 = <1150000>; ++ }; ++ }; + }; + + &cpu0 { +@@ -132,6 +199,10 @@ + cpu-supply = <&vdd_arm>; + }; + ++&dfi { ++ status = "okay"; ++}; ++ + &display_subsystem { + status = "disabled"; + }; +@@ -199,6 +270,7 @@ + regulator-name = "vdd_log"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1075000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; +@@ -213,6 +285,7 @@ + regulator-name = "vdd_arm"; + regulator-always-on; + regulator-boot-on; ++ regulator-init-microvolt = <1225000>; + regulator-min-microvolt = <712500>; + regulator-max-microvolt = <1450000>; + regulator-ramp-delay = <12500>; diff --git a/lede/target/linux/rockchip/patches-6.6/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch b/lede/target/linux/rockchip/patches-6.6/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch new file mode 100644 index 0000000000..37a60d2a08 --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/991-arm64-dts-rockchip-add-more-cpu-operating-points-for.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Leonidas P. Papadakos +Date: Fri, 1 Mar 2019 21:55:53 +0200 +Subject: [PATCH v2] arm64: dts: rockchip: add more cpu operating points for + RK3328 + +This allows for greater max frequency on rk3328 boards, +increasing performance. + +It has been included in Armbian (a linux distibution for ARM boards) +for a while now without any reported issues + +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1392mhz-opp.patch +https://github.com/armbian/build/blob/master/patch/kernel/rockchip64-default/enable-1512mhz-opp.patch + +Signed-off-by: Leonidas P. Papadakos +--- + arch/arm64/boot/dts/rockchip/rk3328.dtsi | 15 +++++++++++++++ + 1 files changed, 15 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi +@@ -142,6 +142,21 @@ + opp-microvolt = <1300000>; + clock-latency-ns = <40000>; + }; ++ opp-1392000000 { ++ opp-hz = /bits/ 64 <1392000000>; ++ opp-microvolt = <1350000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1512000000 { ++ opp-hz = /bits/ 64 <1512000000>; ++ opp-microvolt = <1450000>; ++ clock-latency-ns = <40000>; ++ }; ++ opp-1608000000 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1450000>; ++ clock-latency-ns = <40000>; ++ }; + }; + + analog_sound: analog-sound { diff --git a/lede/target/linux/rockchip/patches-6.6/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch b/lede/target/linux/rockchip/patches-6.6/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch new file mode 100644 index 0000000000..ee8527a2fc --- /dev/null +++ b/lede/target/linux/rockchip/patches-6.6/992-rockchip-rk3399-overclock-to-2.2-1.8-GHz.patch @@ -0,0 +1,46 @@ +From 04202df5cb497b1934c95211cf43784ef62245a4 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Mon, 18 Oct 2021 12:47:30 +0800 +Subject: [PATCH] rockchip: rk3399: overclock to 2.2/1.8 GHz + +It's stable enough to overclock cpu frequency to 2.2/1.8 GHz, +and for better performance. + +Co-development-by: gzelvis +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi ++++ b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi +@@ -33,6 +33,14 @@ + opp-hz = /bits/ 64 <1416000000>; + opp-microvolt = <1125000 1125000 1250000>; + }; ++ opp06 { ++ opp-hz = /bits/ 64 <1608000000>; ++ opp-microvolt = <1225000>; ++ }; ++ opp07 { ++ opp-hz = /bits/ 64 <1800000000>; ++ opp-microvolt = <1275000>; ++ }; + }; + + cluster1_opp: opp-table-1 { +@@ -72,6 +80,14 @@ + opp-hz = /bits/ 64 <1800000000>; + opp-microvolt = <1200000 1200000 1250000>; + }; ++ opp08 { ++ opp-hz = /bits/ 64 <2016000000>; ++ opp-microvolt = <1250000>; ++ }; ++ opp09 { ++ opp-hz = /bits/ 64 <2208000000>; ++ opp-microvolt = <1325000>; ++ }; + }; + + gpu_opp_table: opp-table-2 { diff --git a/mihomo/component/iface/iface.go b/mihomo/component/iface/iface.go index dd932b4629..1d0219dfac 100644 --- a/mihomo/component/iface/iface.go +++ b/mihomo/component/iface/iface.go @@ -40,16 +40,23 @@ func ResolveInterface(name string) (*Interface, error) { ipNets := make([]netip.Prefix, 0, len(addrs)) for _, addr := range addrs { - ipNet := addr.(*net.IPNet) - ip, _ := netip.AddrFromSlice(ipNet.IP) - - ones, bits := ipNet.Mask.Size() - if bits == 32 { + var pf netip.Prefix + switch ipNet := addr.(type) { + case *net.IPNet: + ip, _ := netip.AddrFromSlice(ipNet.IP) + ones, bits := ipNet.Mask.Size() + if bits == 32 { + ip = ip.Unmap() + } + pf = netip.PrefixFrom(ip, ones) + case *net.IPAddr: + ip, _ := netip.AddrFromSlice(ipNet.IP) ip = ip.Unmap() + pf = netip.PrefixFrom(ip, ip.BitLen()) + } + if pf.IsValid() { + ipNets = append(ipNets, pf) } - - pf := netip.PrefixFrom(ip, ones) - ipNets = append(ipNets, pf) } r[iface.Name] = &Interface{ diff --git a/mihomo/config/config.go b/mihomo/config/config.go index ca86649161..ca179ed051 100644 --- a/mihomo/config/config.go +++ b/mihomo/config/config.go @@ -265,6 +265,7 @@ type RawTun struct { EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint_independent_nat,omitempty"` UDPTimeout int64 `yaml:"udp-timeout" json:"udp_timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex int `yaml:"table-index" json:"table-index"` } type RawTuicServer struct { @@ -1448,6 +1449,7 @@ func parseTun(rawTun RawTun, general *General) error { EndpointIndependentNat: rawTun.EndpointIndependentNat, UDPTimeout: rawTun.UDPTimeout, FileDescriptor: rawTun.FileDescriptor, + TableIndex: rawTun.TableIndex, } return nil diff --git a/mihomo/hub/route/configs.go b/mihomo/hub/route/configs.go index ec0b464ce4..653e43519b 100644 --- a/mihomo/hub/route/configs.go +++ b/mihomo/hub/route/configs.go @@ -91,6 +91,7 @@ type tunSchema struct { EndpointIndependentNat *bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` UDPTimeout *int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor *int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex *int `yaml:"table-index" json:"table-index"` } type tuicServerSchema struct { @@ -209,6 +210,9 @@ func pointerOrDefaultTun(p *tunSchema, def LC.Tun) LC.Tun { if p.FileDescriptor != nil { def.FileDescriptor = *p.FileDescriptor } + if p.TableIndex != nil { + def.TableIndex = *p.TableIndex + } } return def } diff --git a/mihomo/listener/config/tun.go b/mihomo/listener/config/tun.go index 1772c6f5b4..7467e4a6a7 100644 --- a/mihomo/listener/config/tun.go +++ b/mihomo/listener/config/tun.go @@ -49,4 +49,5 @@ type Tun struct { EndpointIndependentNat bool `yaml:"endpoint-independent-nat" json:"endpoint-independent-nat,omitempty"` UDPTimeout int64 `yaml:"udp-timeout" json:"udp-timeout,omitempty"` FileDescriptor int `yaml:"file-descriptor" json:"file-descriptor"` + TableIndex int `yaml:"table-index" json:"table-index"` } diff --git a/mihomo/listener/inbound/tun.go b/mihomo/listener/inbound/tun.go index a1fdebfa4a..51747c4629 100644 --- a/mihomo/listener/inbound/tun.go +++ b/mihomo/listener/inbound/tun.go @@ -40,6 +40,7 @@ type TunOption struct { EndpointIndependentNat bool `inbound:"endpoint_independent_nat,omitempty"` UDPTimeout int64 `inbound:"udp_timeout,omitempty"` FileDescriptor int `inbound:"file-descriptor,omitempty"` + TableIndex int `inbound:"table-index,omitempty"` } func (o TunOption) Equal(config C.InboundConfig) bool { @@ -118,6 +119,7 @@ func NewTun(options *TunOption) (*Tun, error) { EndpointIndependentNat: options.EndpointIndependentNat, UDPTimeout: options.UDPTimeout, FileDescriptor: options.FileDescriptor, + TableIndex: options.TableIndex, }, }, nil } diff --git a/mihomo/listener/listener.go b/mihomo/listener/listener.go index ac60297196..e35061882d 100644 --- a/mihomo/listener/listener.go +++ b/mihomo/listener/listener.go @@ -823,7 +823,8 @@ func hasTunConfigChange(tunConf *LC.Tun) bool { LastTunConf.StrictRoute != tunConf.StrictRoute || LastTunConf.EndpointIndependentNat != tunConf.EndpointIndependentNat || LastTunConf.UDPTimeout != tunConf.UDPTimeout || - LastTunConf.FileDescriptor != tunConf.FileDescriptor { + LastTunConf.FileDescriptor != tunConf.FileDescriptor || + LastTunConf.TableIndex != tunConf.TableIndex { return true } diff --git a/mihomo/listener/sing_tun/server.go b/mihomo/listener/sing_tun/server.go index cc26d37dcc..96ec1573f2 100644 --- a/mihomo/listener/sing_tun/server.go +++ b/mihomo/listener/sing_tun/server.go @@ -112,6 +112,10 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis } else { udpTimeout = int64(sing.UDPTimeout.Seconds()) } + tableIndex := options.TableIndex + if tableIndex == 0 { + tableIndex = 2022 + } includeUID := uidToRange(options.IncludeUID) if len(options.IncludeUIDRange) > 0 { var err error @@ -225,7 +229,7 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis ExcludePackage: options.ExcludePackage, FileDescriptor: options.FileDescriptor, InterfaceMonitor: defaultInterfaceMonitor, - TableIndex: 2022, + TableIndex: tableIndex, } err = l.buildAndroidRules(&tunOptions) diff --git a/naiveproxy/CHROMIUM_VERSION b/naiveproxy/CHROMIUM_VERSION index d5a4cb6e63..9e1d4d62dc 100644 --- a/naiveproxy/CHROMIUM_VERSION +++ b/naiveproxy/CHROMIUM_VERSION @@ -1 +1 @@ -122.0.6261.43 +123.0.6312.40 diff --git a/naiveproxy/src/AUTHORS b/naiveproxy/src/AUTHORS index fcfaddcdc4..0b7fa4f14b 100644 --- a/naiveproxy/src/AUTHORS +++ b/naiveproxy/src/AUTHORS @@ -814,6 +814,7 @@ Lenny Khazan Leo Wolf Leon Han Leung Wing Chung +Levi Zim Li Yanbo Li Yin Lian Ruilong @@ -867,6 +868,7 @@ Manuel Palenzuela Merino Mao Yujie Mao Yujie Marc des Garets +Marcello Balduccini Marcio Caroso Marcin Wiacek Marco Monaco @@ -984,6 +986,7 @@ Nagarjuna Atluri Naiem Shaik Naman Kumar Narula Naman Yadav +Nancy Tillery Naoki Takano Naoto Ono Naresh Pratap Singh @@ -1545,6 +1548,7 @@ Zhenyu Shan Zhibo Wang Zhifei Fang Zhiyuan Ye +Zhongwei Wang Zhou Jun Zhuoyu Qian Ziran Sun @@ -1557,6 +1561,7 @@ Zsolt Borbely 方觉 (Fang Jue) 迷渡 郑苏波 (Super Zheng) +一丝 (Yisi) # Please DO NOT APPEND here. See comments at the top of the file. # END individuals section. diff --git a/naiveproxy/src/DEPS b/naiveproxy/src/DEPS index 972c83d030..6f07f6d3df 100644 --- a/naiveproxy/src/DEPS +++ b/naiveproxy/src/DEPS @@ -241,7 +241,7 @@ vars = { # # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab - 'lacros_sdk_version': '15746.0.0', + 'lacros_sdk_version': '15778.0.0', # Generate location tag metadata to include in tests result data uploaded # to ResultDB. This isn't needed on some configs and the tool that generates @@ -253,7 +253,7 @@ vars = { # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:0d11be367258bfe14a13ff1afcf43a0bc6aedb45', + 'luci_go': 'git_revision:3df60a11d33a59614c0e8d2bccc58d8c30984901', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -272,19 +272,21 @@ vars = { # reclient CIPD package 'reclient_package': 'infra/rbe/client/', # reclient CIPD package version - 'reclient_version': 're_client_version:0.126.0.4aaef37-gomaip', + 'reclient_version': 're_client_version:0.131.1.784ddbb-gomaip', - # screen-ai CIPD package Linux version + # screen-ai CIPD packages # TODO(b/281483558): Use a tag to download the latest version of screen-ai # (e.g. 'version:121.3') and find a way to automate updating //DEPS with it. 'screen_ai_linux': 'x8c4xOQj3V2uyBicjNa2YkN71brkj5FZg157RueHF_oC', + 'screen_ai_macos_amd64': 'STOrwjObcsaURUq2izEeXtnwtRhC5HLOTrcfXssSSioC', + 'screen_ai_macos_arm64': 'bxhon5NsSW9znRLRHd79tTy_bkPCZojzLWb57La9RxsC', # The path of the sysroots.json file. # This is used by vendor builds like Electron. 'sysroots_json_path': 'build/linux/sysroot_scripts/sysroots.json', # siso CIPD package version. - 'siso_version': 'git_revision:c892a2c62436b0d4ffbf1e5c559c73cd0f5c7e31', + 'siso_version': 'git_revision:b52a6552a2e17e34b747fd5d29875fc4aba99da8', # download libaom test data 'download_libaom_testdata': False, @@ -304,38 +306,38 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '05c5d674b2d43ae813314cd749f0392813995748', + 'src_internal_revision': '302c17cb1ff9916cf20177141cdddd21ff2c330b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'c6835e2d5ff641dad9347ce4c2ff79dbc29cf9aa', + 'skia_revision': 'aeae2261c7d380404fb8e53eb6062338c4ba0367', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '15126d82086f526657d8889dfda0bc269e503ff9', + 'v8_revision': 'f0b4342fe7f3849aeb19a1dc77f4c8ad5fd68688', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'f9bad5e27d61e2ab6a7504b1793be5aa14eb1414', + 'angle_revision': 'e17dd5a40854c485cd397e2db55e860175566201', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '2fa7e9b99ae4e70ea5ae2cc9c8d3afb43391384f', + 'swiftshader_revision': 'eb75201a4e0354a36d315dd01077092ec9aa2356', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '4c4f9ab25dab142d7888f3258ab54df24b97b44f', + 'pdfium_revision': '812acaddb5b581c775d49cd25c9590603a054cd6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. # # Note this revision should be updated with # third_party/boringssl/roll_boringssl.py, not roll-dep. - 'boringssl_revision': '414f69504d30d0848b69f6453ea7fb5e88004cb4', + 'boringssl_revision': '23824fa0fed94f4660ffafb15aaea8b317f2c8a6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:17.20240120.1.1', + 'fuchsia_version': 'version:18.20240215.1.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -355,11 +357,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '225f880e2de2a2d2b33fbdad55ca27eca3cdc103', + 'nacl_revision': '48409922fc3877f7ab1e50435571aa8b4cf3dda9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '57617782464411201ce7bbc93b086c1b4d7d84a5', + 'freetype_revision': '47574f7ea445c8bb751da0fa716424c9c29a6807', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -379,15 +381,15 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '6fb0d6a41fa5b42b70e27f9268b03214431de51c', + 'catapult_revision': '9cb2dc6f1b9c56d67fffbb7cf7bb7bb4ee156825', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling chromium_variations # and whatever else without interference from each other. - 'chromium_variations_revision': 'd0dcd8802c22c1ac4a7d112782a4c75f0c6ca8ee', + 'chromium_variations_revision': '70b4eaba995ff3e59135b4e842bb247b40c64809', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '1983b3f517da56c35c91296467458f71ad5b9340', + 'crossbench_revision': 'acbea986f40578f43c88239c78c797f61842e642', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -395,11 +397,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling fuzztest # and whatever else without interference from each other. - 'fuzztest_revision': '12e7428ab0847b1d1dc6c4b89203adfd1f16a1ad', + 'fuzztest_revision': '61d95200e7ece7d121cab26f0c39fbf392e6566e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'e4d13b251b100b3fdd0c846b94453c0597bc251f', + 'devtools_frontend_revision': '0b26a98de1edf1aaa557703354180d8787c769c1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -423,11 +425,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '8917c648bdd68007c96b8ca9995533cc3ee995c2', + 'dawn_revision': 'd1212225281e34b1076f3d1a2e9f4b4486b2d061', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '0e39ce016ee1ec8271aa7216d547917c239db525', + 'quiche_revision': 'efc574e1125251bc1c3195c0c183c843b4c0a1df', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -443,7 +445,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': 'e170c9366090cdc389d5f47ee3c2d7db71d263bc', + 'libavif_revision': 'e88a7535f890c710768cea89b68a1c092da32506', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavifinfo # and whatever else without interference from each other. @@ -451,11 +453,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Speedometer v3.0 # and whatever else without interference from each other. - 'speedometer_3.0_revision': '2ee210ca20767c949c4ff29bdffa1138eb0501fe', + 'speedometer_3.0_revision': '7b1b81ee1319cae44c029fd8336d5e574f51e4e4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '4bdb5000ee7919724530cf89d50969e7b0ed58a7', + 'nearby_revision': '6ad4bf75e2e917571b42201fa2b5f30f8ba534db', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -467,7 +469,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'cros_components_revision': 'ab7bdff32543991f52872c25cecf1f926702dfe3', + 'cros_components_revision': 'caaac730221dc9e0a461e7eedcae4a35a46696bd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -475,11 +477,11 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libcxxabi_revision': '9986707a5f2fc6d5d1ffa7f224a032bdd45c95fd', + 'libcxxabi_revision': 'a7b3d968a3a923886fea64b424bd770e69dc4ea4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'libunwind_revision': 'f400fdb561d4416b59b8f8a33d8ec8b79da60495', + 'libunwind_revision': '8bad7bd6ec30f94bce82f7cb5b58ecbd6ce02996', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -491,7 +493,7 @@ vars = { # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ffmpeg # and whatever else without interference from each other. - 'ffmpeg_revision': '17525de887d54b970ffdd421a0879c1db1952307', + 'ffmpeg_revision': '7c1b0b524c639beeb25363b1d0809ebe5c6efe5e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling beto-core # and whatever else without interference from each other. @@ -499,10 +501,10 @@ vars = { # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '28aa23ffb4c7344914a5b4ac7169f12e5a12333f', + 'libcxx_revision': '834e97d73f13a166af65952fb681071eec87a2c4', # GN CIPD package version. - 'gn_version': 'git_revision:f99e015ac35f689cfdbf46e4eb174e5d2da78d8e', + 'gn_version': 'git_revision:d4f94f9a6c25497b2ce0356bb99a8d202c8c1d32', # ninja CIPD package version. # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja @@ -588,7 +590,7 @@ deps = { }, ], 'dep_type': 'cipd', - 'condition': '(host_os == "mac")', + 'condition': 'checkout_mac', }, 'src/third_party/apache-mac-arm64': { 'packages': [ @@ -598,7 +600,7 @@ deps = { }, ], 'dep_type': 'cipd', - 'condition': '(host_os == "mac")', + 'condition': 'checkout_mac', }, 'src/third_party/apache-linux': { @@ -620,7 +622,7 @@ deps = { } ], 'dep_type': 'cipd', - 'condition': '(host_os == "win")' + 'condition': 'checkout_win' }, 'src/third_party/aosp_dalvik': { @@ -649,7 +651,7 @@ deps = { 'packages': [ { 'package': 'chromium/android_webview/tools/cts_archive', - 'version': 'dMHDxWyIpkzGNem_Z7ywDRj3Y2lUQKM7h4JT87_ejr8C', + 'version': 'Tonx5t-WDQ4lYRaMNn3IEzzOeyaIgtQ0d1ZAv0lRlwEC', }, ], 'condition': 'checkout_android', @@ -823,16 +825,16 @@ deps = { 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '5563dfe6fe203c74d7bfff0f0d79c761eba5719a', + '8e19bf2e0e6c7fd728724293a1b5753e54a03667', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '7474472013397bdb177cda70099f6411a5bd8212', + 'url': Var('chromium_git') + '/website.git' + '@' + '12d09e14812d8390213801bb31d08858a3378fcb', }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'c338a8cf3eea7c3ff8b88f835db1d2230a163252', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '92f42b46a340462e12a28e6038d8b6b377a1c554', 'condition': 'checkout_ios', }, @@ -985,7 +987,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'BW2v6j8vjcVQrdX9fXmf686JtkLjxn-KCWhAE1XT_n4C', + 'version': 'AW0sLOt-9fVfqmf3Sn6qDx60H7hL9fi2rxG9UcoHNdoC', }, ], 'condition': 'checkout_android', @@ -1045,7 +1047,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': 'X7sJxpJN0p6qi1dgpI9-UFA2YDe2O2A1kF0QZjBJpmYC', + 'version': 'h9svnJ7PVwpadvxWMqfDD9NPFiJ4mbLravLcmBYueXgC', }, ], 'condition': 'checkout_android', @@ -1056,7 +1058,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': 'tFbjqslkduDT_-y8WEZlsl9iulzcm3mgienslcU71poC', + 'version': 'tQIUabJkFuwAI7BH20b0nn5fKWSPAa_M8cbkzpIW0VkC', }, ], 'condition': 'checkout_android', @@ -1100,7 +1102,7 @@ deps = { Var('chromium_git') + '/external/github.com/chromium/content_analysis_sdk.git' + '@' + '9a408736204513e0e95dd2ab3c08de0d95963efc', 'src/third_party/dav1d/libdav1d': - Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '47107e384bd1dc25674acf04d000a8cdc6195234', + Var('chromium_git') + '/external/github.com/videolan/dav1d.git' + '@' + '7b15ca13752aac7f0a1c6a56e33fe64d1f7638d4', 'src/third_party/dawn': Var('dawn_git') + '/dawn.git' + '@' + Var('dawn_revision'), @@ -1125,7 +1127,7 @@ deps = { Var('boringssl_git') + '/boringssl.git' + '@' + Var('boringssl_revision'), 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '62ecd463583d09eb7d15b1d410055f30b2c7bcb4', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '6551ac3632eb7236642366f70a2eb865b87a3329', 'src/third_party/cast_core/public/src': Var('chromium_git') + '/cast_core/public' + '@' + '71f51fd6fa45fac73848f65421081edd723297cd', @@ -1160,7 +1162,7 @@ deps = { # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a19bf14ba4d77c545b95d49ffd2e099eae5d6b5e', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e3bbb537f1b360f2bfd33543f13dffed1437a7cc', 'condition': 'checkout_chromeos', }, @@ -1174,14 +1176,14 @@ deps = { Var('chromium_git') + '/external/github.com/google/cpu_features.git' + '@' + '936b9ab5515dead115606559502e3864958f7f6e', 'src/third_party/cpuinfo/src': - Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '76cc10d627add77922dc24521b332a055a4d6d77', + Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + '9484a6c590f831a30c1eec1311568b1a967a89dc', 'src/third_party/crc32c/src': Var('chromium_git') + '/external/github.com/google/crc32c.git' + '@' + 'fa5ade41ee480003d9c5af6f43567ba22e4e17e6', # For Linux and Chromium OS. 'src/third_party/cros_system_api': { - 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + '12d5e386005a211570cfdf9849d2fa6a3b38594b', + 'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'd2229e09bc30d6ceab275991e26a9f3b1d5a74c0', 'condition': 'checkout_linux or checkout_chromeos', }, @@ -1195,13 +1197,13 @@ deps = { }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6fc0c97ab284021b72e3bc962f7fa879ffcad65b', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '280bb93210cf6759498f8227ed439bb7845fce07', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'fcb03cd96f26f08a173b609b952ea6bca095fa72', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '137b308e648fc93655156c2337a2598bf4b00b66', 'condition': 'checkout_src_internal', }, @@ -1209,7 +1211,7 @@ deps = { Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d', 'src/third_party/eigen3/src': - Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '454f89af9d6f3525b1df5f9ef9c86df58bf2d4d3', + Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '7fd7a3f946e5ac152d28dad388cff8bfa1026925', 'src/third_party/emoji-metadata/src': { 'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06', @@ -1241,7 +1243,7 @@ deps = { # Used for embedded builds. CrOS & Linux use the system version. 'src/third_party/fontconfig/src': { - 'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + '2fb3419a92156569bc1ec707401258c922cd0d99', + 'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + '14d466b30a8ab4a9d789977ed94f2c30e7209267', 'condition': 'checkout_linux', }, @@ -1279,7 +1281,7 @@ deps = { Var('chromium_git') + '/external/github.com/khaledhosny/ots.git' + '@' + Var('ots_revision'), 'src/third_party/libgav1/src': - Var('chromium_git') + '/codecs/libgav1.git' + '@' + '35fea10bfdb790cf131ae74a4ee346905f34dc3c', + Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'd2f84e499e046281c4ded2d24d9186e2c54c01d8', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1300,7 +1302,7 @@ deps = { }, 'src/third_party/cardboard/src' : { - 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + '5c9f3066dc14962d1dec9a32ec9d3668641c408d', + 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + 'c8842698f4a9d63cce865e7d6cb75773a4673496', 'condition': 'checkout_android', }, @@ -1361,7 +1363,7 @@ deps = { Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'a622de35ac311c5ad390a7af80724634e5dc61ed', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'bad7ddbf921358177e56fd723c2f59f8041a370f', 'src/third_party/icu4j': { 'packages': [ @@ -1428,7 +1430,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlin_stdlib', - 'version': '7f5xFu_YQrbg_vacQ5mMcUFIkMPpvM_mQ8QERRKYBvUC', + 'version': '-uFeIws_FQzyqmgZlGL37ooRLAD8mwClD33O8rZwnTsC', }, ], 'condition': 'checkout_android', @@ -1439,7 +1441,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/kotlinc', - 'version': '8nR_4qTn61NDCwL0G03LrNZzpgmsu5bbyRGior3fZX8C', + 'version': 'ZrpoPpdqeDMIMIhXyd95yML-ZbNUIKDXSeYiWuxz2J0C', }, ], 'condition': 'checkout_android', @@ -1459,7 +1461,7 @@ deps = { Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd', 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '1a72ea323d65e46eb90d08d492c04891abb91926', + Var('aomedia_git') + '/aom.git' + '@' + 'a2d599c9750e3027d3104770fe74ff5d5d012c13', 'src/third_party/libavif/src': Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'), @@ -1529,7 +1531,7 @@ deps = { }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'b95d17572629c676bdcfd535fb3990b9f6f8fb11', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '3316c11240184851f8ce1c3061db8e22123cf9ed', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da', @@ -1538,7 +1540,7 @@ deps = { Var('chromium_git') + '/webm/libwebp.git' + '@' + 'ca332209cb5567c9b249c86788cb2dbf8847e760', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '04821d1e7d60845525e8db55c7bcd41ef5be9406', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'a6a2ec654b1be1166b376476a7555c89eca0c275', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -1573,7 +1575,7 @@ deps = { }, 'src/third_party/material_color_utilities/src': { - 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-color-utilities.git' + '@' + 'bec7bab60e6431201a82761ea4482b98b54c2af9', + 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-color-utilities.git' + '@' + '13434b50dcb64a482cc91191f8cf6151d90f5465', }, 'src/third_party/material_design_icons/src': { @@ -1650,7 +1652,7 @@ deps = { Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '09a4f3ec842a8932341b195c5b01e141c8a16eb7', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + 'b70c552bedf189fc238e98f8f69e6c30e7925207', + Var('chromium_git') + '/openscreen' + '@' + 'f24b43fe39fde657f63030679c39b3c51a441586', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '95fe35ffb383710a6e0567e958ead9a3b66e930c', @@ -1661,7 +1663,7 @@ deps = { Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '1e15d01da5d619ca617dcdd870efe3c35046a89c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '63b162fccc3b5d601b561e3218322fa3d8b2dcaf', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '8ef97ff3b7332e38e61b347a2fbed425a4617151', @@ -1687,7 +1689,7 @@ deps = { 'packages': [ { 'package': 'fuchsia/third_party/qemu/linux-arm64', - 'version': 'BpnoBb2d44_SOm9toN6Lju5a2RLGAc1TPUO6xyijoP8C' + 'version': 'hOpuGIMj1FAtBWGDlXARkCm2srxY4enn8iI3AgrDna4C' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia and checkout_fuchsia_for_arm64_host', @@ -1695,13 +1697,13 @@ deps = { }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '826ad10e58a042faf57d7c329b0fd0a04b797e0b', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'f9550c3f7207f946a45bbccd1814b12b136aae72', 'src/third_party/r8': { 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'K1NPmXz0aZCAGGtC5UESEmqwT5-x6QNNb0Jo0umsez4C', + 'version': 'h_Nyj61z-U6meQbvpjcxE8NoosFmfjJ_VobRAFrNCjYC', }, ], 'condition': 'checkout_android', @@ -1739,7 +1741,7 @@ deps = { }, 'src/third_party/ruy/src': - Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + 'cd7b92695b5d3f0c9ff65b865c2a1e19b99d766d', + Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '587c2cf8b11d3c32fa26887063eda3171a3d353e', 'src/third_party/skia': Var('skia_git') + '/skia.git' + '@' + Var('skia_revision'), @@ -1751,7 +1753,7 @@ deps = { Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + 'c9f9edf6d75bb065fa47468bf035e051a57bec7c', 'src/third_party/sqlite/src': - Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + 'a5270ae741714a5aad187ba8dcd8bddca39f791f', + Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + '0c0e07d7de6bac46cb28fbf6c576a4e13de15553', 'src/third_party/sqlite4java': { 'packages': [ @@ -1793,27 +1795,27 @@ deps = { Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f', 'src/third_party/tflite/src': - Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '296f1e3cce03308c7fd5cdc7a76fbc3e41ec5214', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'e65a2c7a59555735b58cea92e1571e7ced1b6bbf', 'src/third_party/turbine': { 'packages': [ { 'package': 'chromium/third_party/turbine', - 'version': 'KfCqNpZ5XxbfuKiIsjeMWFX-6aJc5WN37x9weHyVDIkC', + 'version': 's-hdujub30RR2mH9Qf7pHv6h9uNGEiYVs6W1VXWeEe8C', }, ], 'condition': 'checkout_android', 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@c00c99b8e979ca1b1eba221a60cb1e1d3b12f956', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@9c80a66222a9f2f4f02b80b383bb378bfc236559', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', # Display server protocol for Linux. 'src/third_party/wayland/src': { - 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland.git' + '@' + 'af7f44122127b86a8c74cb7432909180f4899eaa', + 'url': Var('chromium_git') + '/external/anongit.freedesktop.org/git/wayland/wayland.git' + '@' + 'c35d1a3d1c0a1735afe5eb227cb826faa878ec19', 'condition': 'checkout_linux', }, @@ -1843,10 +1845,10 @@ deps = { Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'f4bf599a8b575df685c31d9c4729a70a04e377ed', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e082b08475761a2ba6a3349dfea72f704c8b68d4', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '8a9294d00391a8d3dbcdb3091308f9b3034b384e', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'be2786cd2383b7ec5d158add166275d19e246763', + Var('webrtc_git') + '/src.git' + '@' + '41b1493ddb5d98e9125d5cb002fd57ce76ebd8a7', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1871,7 +1873,7 @@ deps = { }, 'src/third_party/xnnpack/src': - Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'a68aa0a24b0d3e1c75f2f7c0915b70121cee0470', + Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'd5d373fee053b4823f37611f88a51d6c8e23d42a', 'src/tools/page_cycler/acid3': Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + 'a926d0a32e02c4c03ae95bb798e6c780e0e184ba', @@ -1890,13 +1892,13 @@ deps = { }, 'src/third_party/zstd/src': - Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '050fec5c378d676fede8b2171ec5e84f6afa1504', + Var('chromium_git') + '/external/github.com/facebook/zstd.git' + '@' + '621a263fb2e6c2175fbd489e5d77ee8038baa2b2', 'src/tools/skia_goldctl/linux': { 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': '407H-TbIdlUjRbGWaMLTbSuhauPqvPICdysGuqJvZwUC', + 'version': 'zK5gXUdYtOJO_5L0VqpL13_iPtatoApMRsbAJ-AObycC', }, ], 'dep_type': 'cipd', @@ -1906,7 +1908,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': '14DPIsHsHs60_8PzIoLPiLesYnsN_0qV7RUmyNCr3zMC', + 'version': 'fWJiw3sBoMGqR2SS2otkCsOmnqK4iXZUWzTVfqw0cssC', }, ], 'dep_type': 'cipd', @@ -1917,7 +1919,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'lkI4UMXstA7DR9LqFykhbBB0sT-pbajdPVIN8nO1xCwC', + 'version': 'I77LRdzh6aOopDPydG6LuPfDh6BbH4IFqWH8WWesWlMC', }, ], 'dep_type': 'cipd', @@ -1928,7 +1930,7 @@ deps = { 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'lhItSTy1WLT7ZDUaklin1sNQ2vdQFPwVcEKC5gRty-4C', + 'version': 'JRekXzEdC8R2yKoqGJvHhZ516qC1pJwyHAxOuqTyDREC', }, ], 'dep_type': 'cipd', @@ -1958,7 +1960,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/eche_app/app', - 'version': '21ioGwVFXWwczZxLxJkLx5Ip0yA9YW9K5gjEdV_NO3gC', + 'version': 'DnPrMxwYi3z-CBmheuwa4UpmeI5g0AUOWlPLCPDLbA4C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1969,7 +1971,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'T2L4eCZoLBfD5jbAfm6CtGFubQrFsh8hBTH_gG6UyewC', + 'version': 'JwGf5qZw7PgrQ4euqRl9iGhcEshUiYD1QgEUXQ6yXQUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1980,7 +1982,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'lB6ZFaZwsZsfLvlQn7y4X3B8129MDO3G2A5iBrhuUnQC', + 'version': 's5jT7WEmP1U58wei6ziA4mnu0N_9GwpRxpPLHlJIcssC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2013,7 +2015,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'je0l3f95yPXSEJdiw4B20oNpQ4qtxwkdWYRdPDyt3MUC', + 'version': 'PN-QPiUgJg3wDh9RD3r6W75wsH8HV-1itFHINs0IRBIC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2449,7 +2451,7 @@ deps = { 'packages': [ { 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_base', - 'version': 'version:2@18.0.1.cr1', + 'version': 'version:2@18.1.0.cr1', }, ], 'condition': 'checkout_android', @@ -2610,6 +2612,28 @@ deps = { 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/com_google_android_gms_play_services_tflite_impl': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tflite_impl', + 'version': 'version:2@16.0.1.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + + 'src/third_party/android_deps/libs/com_google_android_gms_play_services_tflite_java': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tflite_java', + 'version': 'version:2@16.0.1.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/android_deps/libs/com_google_android_gms_play_services_vision': { 'packages': [ { @@ -3369,6 +3393,28 @@ deps = { 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_android_extensions_runtime', + 'version': 'version:2@1.9.22.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + + 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_parcelize_runtime', + 'version': 'version:2@1.9.22.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': { 'packages': [ { @@ -3391,6 +3437,17 @@ deps = { 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlinx_atomicfu_jvm', + 'version': 'version:2@0.23.2.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + 'src/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_coroutines_android': { 'packages': [ { @@ -3710,6 +3767,17 @@ deps = { 'dep_type': 'cipd', }, + 'src/third_party/android_deps/libs/org_tensorflow_tensorflow_lite_api': { + 'packages': [ + { + 'package': 'chromium/third_party/android_deps/libs/org_tensorflow_tensorflow_lite_api', + 'version': 'version:2@2.10.0.cr1', + }, + ], + 'condition': 'checkout_android', + 'dep_type': 'cipd', + }, + # === ANDROID_DEPS Generated Code End === 'src/tools/resultdb': { @@ -3761,7 +3829,7 @@ deps = { # Dependencies from src_internal 'src/chromeos/assistant/internal': { 'url': Var('chrome_git') + '/chrome/assistant.git' + '@' + - 'a2f5b174dbc4f5a6ceb9757e9f292ff17015d7ad', + 'aebc822b20c2e472e3bb7e44541f06032b0dd0e3', 'condition': 'checkout_src_internal and checkout_chromeos', }, @@ -3828,15 +3896,21 @@ deps = { 'condition': 'checkout_src_internal', }, + 'src/chrome/browser/platform_experience/win': { + 'url': Var('chrome_git') + '/chrome/browser/platform_experience/win.git' + '@' + + '6383a08573bf06dbcd51da6aceffc86c59cc25f4', + 'condition': 'checkout_src_internal', + }, + 'src/chrome/browser/resources/chromeos/quickoffice': { 'url': Var('chrome_git') + '/quickoffice/crx.git' + '@' + - '79e797d69d4675a2f0ef916dbb65457fe9485fc9', + '82b2a09bf9550c7435a774a6261e6736b787468f', 'condition': '(checkout_chromeos or checkout_linux) and checkout_src_internal', }, - 'src/chrome/browser/resources/settings_internal': { + 'src/chrome/browser/resources/settings/internal': { 'url': Var('chrome_git') + '/chrome/browser/resources/settings_internal.git' + '@' + - '5d6316b2434986e6b073e1d24585578bb27da451', # from svn revision 41419 + 'c8a62277e90b0e4cea284f3ba188d5e1cbfc07ab', # from svn revision 41419 'condition': 'checkout_src_internal', }, @@ -3850,7 +3924,18 @@ deps = { 'packages' : [ { 'package': 'chromeos_internal/inputs/orca', - 'version': 'idj872EVym3y6rYM9KjpQ6G60oEODlVB2hombAuFCbIC' + 'version': 'ex3HfXjUIRsuf6fz72kUP11zauou3laDZ_sumsrLL3wC' + } + ], + 'condition': 'checkout_chromeos and checkout_src_internal', + 'dep_type': 'cipd', + }, + + 'src/chrome/browser/resources/chromeos/seal/resources': { + 'packages' : [ + { + 'package': 'chromeos_internal/inputs/seal', + 'version': '11AdGL1RBEo2LflLT5Vc8Q3vBfjsHQAuH5jAhUBxL9QC' } ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3949,13 +4034,13 @@ deps = { 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '69f890a1800e03a26267a4e72a051a7c121082f1', + '0cee66b28caba679736c2e63ccb3a76e99f941fa', 'condition': 'checkout_src_internal', }, 'src/components/plus_addresses/resources/internal': { 'url': Var('chrome_git') + '/chrome/components/plus_addresses/resources.git' + '@' + - '61a9cd635c8317c7c4be901936629e12b2bdea3c', + '4f595c87a18088bf7c43613ebae849f23559f725', 'condition': 'checkout_src_internal', }, @@ -4009,7 +4094,7 @@ deps = { 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '448586e33e09467fc54287f4ac6149426bc250b2', + '6c5287d7adda0ea7efec7575cc51d6df4c3ac2b5', 'condition': 'checkout_ios and checkout_src_internal', }, @@ -4027,7 +4112,7 @@ deps = { 'src/remoting/internal': { 'url': Var('chrome_git') + '/chrome/remoting/internal.git' + '@' + - '55265d75e1b3025a2fdcc317397d0fc5a53c0162', + '7a922bc6f3b96a6aaf7eb741df3492248a842aea', 'condition': 'checkout_src_internal', }, @@ -4085,7 +4170,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/x64/internal', - 'version': 'w-9I4ZQe75ope7clwip3vo3wXzm-hDaF9qEDmzi8DNsC', + 'version': 'ONBUvln4HGgBn4B4uwD_GLKwHKk4XtyBTTcb0VqLqBUC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4096,7 +4181,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/arm64/internal', - 'version': 'L2pNmE15We5ZW21b6dgA3i6mZ_ELXcg_GIZrJQSa5yUC', + 'version': '8tJ92R7a1cME_3Lb8dY17jMPhIZmJKGn74jRcvBwDA8C', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4107,7 +4192,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_device/arm/internal', - 'version': 'ZdMISVwM_Me_supqNeYFtIoqPR9ZnD9TWghBQs-EZgQC', + 'version': 'HWbMkz4ukSFB4WDMHQokyqvncNrDQdykTNAFPxMiXSYC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4118,7 +4203,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/libassistant_cros_glinux/x64/internal', - 'version': 'ymOO8fysuXlIs5oqwgsZ6jFP1QDPzx4TYnzwgmn77a4C', + 'version': 'CHE67HLb-6imPXB3fBp_A_eFs2kf_lg-sU5xH2q_bmYC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4129,7 +4214,7 @@ deps = { 'packages': [ { 'package': 'chromeos_internal/assistant/libassistant/fake_s3_server_cros_glinux/x64/internal', - 'version': 'oldnb3_NMrgx9lBYJD43rCLL0TAiVBMJMbpFlgXnOfIC', + 'version': 'IRweCdbYxKDjyJ0cm9uNuSdHydlV75Nrw3eUboDEAPYC', }, ], 'condition': 'checkout_src_internal and checkout_chromeos', @@ -4147,6 +4232,28 @@ deps = { 'dep_type': 'cipd', }, + 'src/third_party/screen-ai/macos_amd64': { + 'packages': [ + { + 'package': 'chromium/third_party/screen-ai/mac-amd64', + 'version': Var('screen_ai_macos_amd64'), + }, + ], + 'condition': 'checkout_mac', + 'dep_type': 'cipd', + }, + + 'src/third_party/screen-ai/macos_arm64': { + 'packages': [ + { + 'package': 'chromium/third_party/screen-ai/mac-arm64', + 'version': Var('screen_ai_macos_arm64'), + }, + ], + 'condition': 'checkout_mac', + 'dep_type': 'cipd', + }, + 'src/third_party/soda': { 'packages': [ { @@ -4979,7 +5086,7 @@ hooks = [ { 'name': 'Fetch WPR archive files', 'pattern': '.', - 'condition': 'checkout_android and (checkout_wpr_archives or checkout_src_internal)', + 'condition': 'checkout_android and checkout_wpr_archives', 'action': [ 'python3', 'src/chrome/test/data/android/manage_wpr_archives.py', 'download', @@ -5367,7 +5474,8 @@ hooks = [ 'condition': 'checkout_pgo_profiles and checkout_lacros_sdk', 'action': [ 'python3', 'src/tools/update_pgo_profiles.py', - '--target=lacros-arm', + # Use arm64 profile. + '--target=lacros-arm64', 'update', '--gs-url-base=chromium-optimization-profiles/pgo_profiles', ], diff --git a/naiveproxy/src/base/BUILD.gn b/naiveproxy/src/base/BUILD.gn index f1c58f35c3..34c123234c 100644 --- a/naiveproxy/src/base/BUILD.gn +++ b/naiveproxy/src/base/BUILD.gn @@ -42,6 +42,11 @@ import("//build/timestamp.gni") import("//build/util/process_version.gni") import("//build_overrides/build.gni") +if (is_ios) { + # Used to access ios_is_app_extension variable definition. + import("//build/config/ios/ios_sdk.gni") +} + if (is_mac) { # Used to generate fuzzer corpus :base_mach_port_rendezvous_convert_corpus. import("//third_party/protobuf/proto_library.gni") @@ -285,7 +290,6 @@ component("base") { "containers/lru_cache.h", "containers/map_util.h", "containers/small_map.h", - "containers/span.h", "containers/stack.h", "containers/unique_ptr_adapters.h", "containers/util.h", @@ -405,6 +409,7 @@ component("base") { "memory/platform_shared_memory_mapper.h", "memory/platform_shared_memory_region.cc", "memory/platform_shared_memory_region.h", + "memory/protected_memory.h", "memory/ptr_util.h", "memory/raw_ptr.h", "memory/raw_ptr_asan_bound_arg_tracker.cc", @@ -488,8 +493,6 @@ component("base") { "metrics/histogram_macros_local.h", "metrics/histogram_samples.cc", "metrics/histogram_samples.h", - "metrics/histogram_shared_memory.cc", - "metrics/histogram_shared_memory.h", "metrics/histogram_snapshot_manager.cc", "metrics/histogram_snapshot_manager.h", "metrics/metrics_hashes.cc", @@ -518,6 +521,7 @@ component("base") { "metrics/user_metrics_action.h", "no_destructor.h", "not_fatal_until.h", + "notimplemented.h", "notreached.h", "observer_list.h", "observer_list_internal.cc", @@ -782,9 +786,6 @@ component("base") { "task/thread_pool/environment_config.h", "task/thread_pool/job_task_source.cc", "task/thread_pool/job_task_source.h", - "task/thread_pool/job_task_source_interface.h", - "task/thread_pool/job_task_source_old.cc", - "task/thread_pool/job_task_source_old.h", "task/thread_pool/pooled_parallel_task_runner.cc", "task/thread_pool/pooled_parallel_task_runner.h", "task/thread_pool/pooled_sequenced_task_runner.cc", @@ -812,6 +813,8 @@ component("base") { "task/thread_pool/thread_group.h", "task/thread_pool/thread_group_impl.cc", "task/thread_pool/thread_group_impl.h", + "task/thread_pool/thread_group_semaphore.cc", + "task/thread_pool/thread_group_semaphore.h", "task/thread_pool/thread_group_worker_delegate.cc", "task/thread_pool/thread_group_worker_delegate.h", "task/thread_pool/thread_pool_impl.cc", @@ -916,6 +919,8 @@ component("base") { "trace_event/heap_profiler_allocation_context_tracker.h", "trace_event/memory_allocator_dump_guid.cc", "trace_event/memory_allocator_dump_guid.h", + "trace_event/named_trigger.cc", + "trace_event/named_trigger.h", "trace_event/trace_id_helper.cc", "trace_event/trace_id_helper.h", "traits_bag.h", @@ -927,6 +932,7 @@ component("base") { "types/expected_macros.h", "types/fixed_array.h", "types/id_type.h", + "types/is_complete.h", "types/is_instantiation.h", "types/optional_ref.h", "types/optional_util.h", @@ -1056,6 +1062,7 @@ component("base") { "//base/third_party/dynamic_annotations", "//build:blink_buildflags", "//build:branding_buildflags", + "//build:ios_buildflags", "//build/config/compiler:compiler_buildflags", "//third_party/modp_b64", ] @@ -1086,6 +1093,7 @@ component("base") { ":orderfile_buildflags", ":power_monitor_buildflags", ":profiler_buildflags", + ":protected_memory_buildflags", ":rust_buildflags", ":sanitizer_buildflags", ":synchronization_buildflags", @@ -1197,7 +1205,7 @@ component("base") { deps += [ "//third_party/ashmem", "//third_party/cpu_features:ndk_compat", - "//third_party/jni_zero:jni_zero_utils", + "//third_party/jni_zero:jni_zero", ] # Needs to be a public config so that dependent targets link against it as @@ -1255,6 +1263,9 @@ component("base") { "android/jni_android.h", "android/jni_array.cc", "android/jni_array.h", + "android/jni_bytebuffer.cc", + "android/jni_bytebuffer.h", + "android/jni_conversions.cc", "android/jni_registrar.cc", "android/jni_registrar.h", "android/jni_string.cc", @@ -1267,14 +1278,17 @@ component("base") { "android/library_loader/library_loader_hooks.h", "android/native_uma_recorder.cc", "android/scoped_java_ref.h", + "android/token_android.cc", + "android/token_android.h", "android/trace_event_binding.cc", "android/trace_event_binding.h", ] deps += [ ":base_jni", ":process_launcher_jni", + "//build:robolectric_buildflags", ] - public_deps += [ "//third_party/jni_zero:jni_zero_utils" ] + public_deps += [ "//third_party/jni_zero:jni_zero" ] } # is_android || is_robolectric # Chromeos. @@ -1307,7 +1321,6 @@ component("base") { "files/dir_reader_posix.h", "files/file_path_watcher_stub.cc", # See crbug.com/851641. "files/file_posix.cc", - "files/file_util_fuchsia.cc", "files/memory_mapped_file_posix.cc", "fuchsia/default_job.cc", "fuchsia/default_job.h", @@ -1603,6 +1616,10 @@ component("base") { sources += [ "memory/discardable_shared_memory.cc", "memory/discardable_shared_memory.h", + "memory/shared_memory_switch.cc", + "memory/shared_memory_switch.h", + "metrics/histogram_shared_memory.cc", + "metrics/histogram_shared_memory.h", "process/kill.cc", "process/kill.h", "process/launch.cc", @@ -1676,6 +1693,7 @@ component("base") { "memory/page_size_win.cc", "memory/platform_shared_memory_mapper_win.cc", "memory/platform_shared_memory_region_win.cc", + "memory/protected_memory_win.cc", "message_loop/message_pump_win.cc", "message_loop/message_pump_win.h", "moving_window.h", @@ -2029,7 +2047,6 @@ component("base") { sources += [ "base_paths_ios.h", "base_paths_ios.mm", - "critical_closure_internal_ios.mm", "ios/block_types.h", "ios/crb_protocol_observers.h", "ios/crb_protocol_observers.mm", @@ -2040,8 +2057,6 @@ component("base") { "ios/ns_error_util.h", "ios/ns_error_util.mm", "ios/ns_range.h", - "ios/scoped_critical_action.h", - "ios/scoped_critical_action.mm", "native_library_ios.mm", "power_monitor/power_monitor_device_source_ios.mm", "process/process_metrics_ios.cc", @@ -2050,6 +2065,14 @@ component("base") { "system/sys_info_ios.mm", ] + if (!ios_is_app_extension) { + sources += [ + "critical_closure_internal_ios.mm", + "ios/scoped_critical_action.h", + "ios/scoped_critical_action.mm", + ] + } + if (use_blink) { sources += [ "files/file_path_watcher_kqueue.cc", @@ -2453,6 +2476,17 @@ buildflag_header("orderfile_buildflags") { ] } +# Build flags for ProtectedMemory +buildflag_header("protected_memory_buildflags") { + header = "protected_memory_buildflags.h" + header_dir = "base/memory" + + # Currently Protected Memory is only supported on Windows. + protected_memory_enabled = is_win + + flags = [ "PROTECTED_MEMORY_ENABLED=$protected_memory_enabled" ] +} + buildflag_header("synchronization_buildflags") { header = "synchronization_buildflags.h" header_dir = "base/synchronization" diff --git a/naiveproxy/src/base/OWNERS b/naiveproxy/src/base/OWNERS index 9501e57661..255a11e0b0 100644 --- a/naiveproxy/src/base/OWNERS +++ b/naiveproxy/src/base/OWNERS @@ -41,6 +41,8 @@ per-file dcheck*=olivierli@chromium.org per-file dcheck*=pbos@chromium.org per-file logging*=olivierli@chromium.org per-file logging*=pbos@chromium.org +per-file notimplemented.h=olivierli@chromium.org +per-file notimplemented.h=pbos@chromium.org per-file notreached.h=olivierli@chromium.org per-file notreached.h=pbos@chromium.org diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.cc b/naiveproxy/src/base/allocator/partition_alloc_features.cc index 1ba2c0639e..0a320b841e 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_features.cc @@ -8,6 +8,7 @@ #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/time/time.h" #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h" #include "base/allocator/partition_allocator/src/partition_alloc/partition_root.h" +#include "base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h" #include "base/allocator/partition_allocator/src/partition_alloc/thread_cache.h" #include "base/base_export.h" #include "base/feature_list.h" @@ -118,11 +119,6 @@ BASE_FEATURE(kPartitionAllocSchedulerLoopQuarantine, const base::FeatureParam kPartitionAllocSchedulerLoopQuarantineCapacity{ &kPartitionAllocSchedulerLoopQuarantine, "PartitionAllocSchedulerLoopQuarantineCapacity", 0}; -// Scheduler Loop Quarantine's capacity count. -const base::FeatureParam - kPartitionAllocSchedulerLoopQuarantineCapacityCount{ - &kPartitionAllocSchedulerLoopQuarantine, - "PartitionAllocSchedulerLoopQuarantineCapacityCount", 1024}; BASE_FEATURE(kPartitionAllocZappingByFreeFlags, "PartitionAllocZappingByFreeFlags", @@ -178,19 +174,29 @@ constexpr FeatureParam::Option kBackupRefPtrModeOptions[] = { }; const base::FeatureParam kBackupRefPtrModeParam{ - &kPartitionAllocBackupRefPtr, "brp-mode", BackupRefPtrMode::kEnabled, - &kBackupRefPtrModeOptions}; + &kPartitionAllocBackupRefPtr, "brp-mode", + BackupRefPtrMode::kEnabledInSameSlotMode, &kBackupRefPtrModeOptions}; BASE_FEATURE(kPartitionAllocMemoryTagging, "PartitionAllocMemoryTagging", - FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(USE_FULL_MTE) + FEATURE_ENABLED_BY_DEFAULT +#else + FEATURE_DISABLED_BY_DEFAULT +#endif +); constexpr FeatureParam::Option kMemtagModeOptions[] = { {MemtagMode::kSync, "sync"}, {MemtagMode::kAsync, "async"}}; const base::FeatureParam kMemtagModeParam{ - &kPartitionAllocMemoryTagging, "memtag-mode", MemtagMode::kAsync, + &kPartitionAllocMemoryTagging, "memtag-mode", +#if BUILDFLAG(USE_FULL_MTE) + MemtagMode::kSync, +#else + MemtagMode::kAsync, +#endif &kMemtagModeOptions}; constexpr FeatureParam::Option @@ -202,7 +208,11 @@ constexpr FeatureParam::Option const base::FeatureParam kMemoryTaggingEnabledProcessesParam{ &kPartitionAllocMemoryTagging, "enabled-processes", +#if BUILDFLAG(USE_FULL_MTE) + MemoryTaggingEnabledProcesses::kAllProcesses, +#else MemoryTaggingEnabledProcesses::kBrowserOnly, +#endif &kMemoryTaggingEnabledProcessesOptions}; BASE_FEATURE(kKillPartitionAllocMemoryTagging, @@ -212,7 +222,13 @@ BASE_FEATURE(kKillPartitionAllocMemoryTagging, BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPermissiveMte); BASE_FEATURE(kPartitionAllocPermissiveMte, "PartitionAllocPermissiveMte", - FEATURE_ENABLED_BY_DEFAULT); +#if BUILDFLAG(USE_FULL_MTE) + // We want to actually crash if USE_FULL_MTE is enabled. + FEATURE_DISABLED_BY_DEFAULT +#else + FEATURE_ENABLED_BY_DEFAULT +#endif +); const base::FeatureParam kBackupRefPtrAsanEnableDereferenceCheckParam{ &kPartitionAllocBackupRefPtr, "asan-enable-dereference-check", true}; @@ -437,5 +453,51 @@ BASE_FEATURE(kUsePoolOffsetFreelists, base::FEATURE_DISABLED_BY_DEFAULT); #endif +BASE_FEATURE(kPartitionAllocMakeFreeNoOpOnShutdown, + "PartitionAllocMakeFreeNoOpOnShutdown", + FEATURE_DISABLED_BY_DEFAULT); + +constexpr FeatureParam::Option + kPartitionAllocMakeFreeNoOpOnShutdownOptions[] = { + { + WhenFreeBecomesNoOp::kBeforeShutDownThreads, + "before-shutdown-threads", + }, + { + WhenFreeBecomesNoOp::kInShutDownThreads, + "in-shutdown-threads", + }, + { + WhenFreeBecomesNoOp::kAfterShutDownThreads, + "after-shutdown-threads", + }, +}; + +const base::FeatureParam + kPartitionAllocMakeFreeNoOpOnShutdownParam{ + &kPartitionAllocMakeFreeNoOpOnShutdown, "callsite", + WhenFreeBecomesNoOp::kBeforeShutDownThreads, + &kPartitionAllocMakeFreeNoOpOnShutdownOptions}; + +void MakeFreeNoOp(WhenFreeBecomesNoOp callsite) { + CHECK(base::FeatureList::GetInstance()); + // Ignoring `free()` during Shutdown would allow developers to introduce new + // dangling pointers. So we want to avoid ignoring free when it is enabled. + // Note: For now, the DanglingPointerDetector is only enabled on 5 bots, and + // on linux non-official configuration. + // TODO(b/40802063): Reconsider this decision after the experiment. +#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) + if (base::FeatureList::IsEnabled(features::kPartitionAllocDanglingPtr)) { + return; + } +#endif // BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS) +#if BUILDFLAG(USE_ALLOCATOR_SHIM) + if (base::FeatureList::IsEnabled(kPartitionAllocMakeFreeNoOpOnShutdown) && + kPartitionAllocMakeFreeNoOpOnShutdownParam.Get() == callsite) { + allocator_shim::InsertNoOpOnFreeAllocatorShimOnShutDown(); + } +#endif // BUILDFLAG(USE_ALLOCATOR_SHIM) +} + } // namespace features } // namespace base diff --git a/naiveproxy/src/base/allocator/partition_alloc_features.h b/naiveproxy/src/base/allocator/partition_alloc_features.h index f1d1d7f1e8..fab692b252 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_features.h +++ b/naiveproxy/src/base/allocator/partition_alloc_features.h @@ -75,9 +75,6 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSchedulerLoopQuarantine); // Scheduler Loop Quarantine's capacity in bytes. extern const BASE_EXPORT base::FeatureParam kPartitionAllocSchedulerLoopQuarantineCapacity; -// Scheduler Loop Quarantine's capacity count. -extern const BASE_EXPORT base::FeatureParam - kPartitionAllocSchedulerLoopQuarantineCapacityCount; BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags); #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) @@ -129,6 +126,23 @@ enum class BucketDistributionMode : uint8_t { kDenser, }; +// Parameter for 'kPartitionAllocMakeFreeNoOpOnShutdown' feature which +// controls when free() becomes a no-op during Shutdown() +enum class WhenFreeBecomesNoOp { + // Allocator is inserted either before, in, or after shutdown threads + kBeforeShutDownThreads, + kInShutDownThreads, + kAfterShutDownThreads, +}; + +// Inserts a no-op on 'free()' allocator shim at the front of the +// dispatch chain if called from the appropriate callsite. +BASE_EXPORT void MakeFreeNoOp(WhenFreeBecomesNoOp callsite); + +BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocMakeFreeNoOpOnShutdown); +extern const BASE_EXPORT base::FeatureParam + kPartitionAllocMakeFreeNoOpOnShutdownParam; + BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocBackupRefPtr); extern const BASE_EXPORT base::FeatureParam kBackupRefPtrEnabledProcessesParam; diff --git a/naiveproxy/src/base/allocator/partition_alloc_support.cc b/naiveproxy/src/base/allocator/partition_alloc_support.cc index c18d7bf3ca..d6bc52d50d 100644 --- a/naiveproxy/src/base/allocator/partition_alloc_support.cc +++ b/naiveproxy/src/base/allocator/partition_alloc_support.cc @@ -4,7 +4,6 @@ #include "base/allocator/partition_alloc_support.h" -#include #include #include #include @@ -364,8 +363,11 @@ std::map ProposeSyntheticFinchTrials() { #if BUILDFLAG(IS_ANDROID) BootloaderOverride bootloader_override = GetBootloaderOverride(); partition_alloc::TagViolationReportingMode reporting_mode = - allocator_shim::internal::PartitionAllocMalloc::Allocator() - ->memory_tagging_reporting_mode(); + partition_alloc::TagViolationReportingMode::kUndefined; +#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) + reporting_mode = allocator_shim::internal::PartitionAllocMalloc::Allocator() + ->memory_tagging_reporting_mode(); +#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) switch (bootloader_override) { case BootloaderOverride::kDefault: trials.emplace("MemoryTaggingBootloaderOverride", "Default"); @@ -669,7 +671,7 @@ void CheckDanglingRawPtrBufferEmpty() { std::vector> stack_traces = internal::InstanceTracer::GetStackTracesForDanglingRefs(entry->id); for (const auto& raw_stack_trace : stack_traces) { - LOG(ERROR) << "Live reference from:\n"; + LOG(ERROR) << "Dangling reference from:\n"; LOG(ERROR) << debug::StackTrace(raw_stack_trace.data(), raw_stack_trace.size() - static_cast(ranges::count( @@ -1129,9 +1131,6 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit( const size_t scheduler_loop_quarantine_capacity_in_bytes = static_cast( base::features::kPartitionAllocSchedulerLoopQuarantineCapacity.Get()); - const size_t scheduler_loop_quarantine_capacity_count = static_cast( - base::features::kPartitionAllocSchedulerLoopQuarantineCapacityCount - .Get()); const bool zapping_by_free_flags = base::FeatureList::IsEnabled( base::features::kPartitionAllocZappingByFreeFlags); @@ -1210,7 +1209,6 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit( memory_tagging_reporting_mode, bucket_distribution, allocator_shim::SchedulerLoopQuarantine(scheduler_loop_quarantine), scheduler_loop_quarantine_capacity_in_bytes, - scheduler_loop_quarantine_capacity_count, allocator_shim::ZappingByFreeFlags(zapping_by_free_flags)); const uint32_t extras_size = allocator_shim::GetMainPartitionRootExtrasSize(); diff --git a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni index 89d624a74f..9c4f6561f6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni +++ b/naiveproxy/src/base/allocator/partition_allocator/partition_alloc.gni @@ -234,6 +234,16 @@ declare_args() { enable_shadow_metadata = false } +declare_args() { + # Use full MTE protection available by changing the feature flag default + # values. So sync mode on all processes. Also disables permissive MTE. + # + # This is meant to be used primarily on bots. It is much easier to override + # the feature flags using a binary flag instead of updating multiple bots's + # scripts to pass command line arguments. + use_full_mte = false +} + # *Scan is currently only used by Chromium, and supports only 64-bit. use_starscan = build_with_chromium && has_64_bit_pointers @@ -258,11 +268,13 @@ if (!use_partition_alloc) { use_hookable_raw_ptr = false enable_backup_ref_ptr_slow_checks = false enable_dangling_raw_ptr_checks = false + enable_dangling_raw_ptr_feature_flag = false enable_dangling_raw_ptr_perf_experiment = false enable_pointer_subtraction_check = false backup_ref_ptr_poison_oob_ptr = false enable_backup_ref_ptr_instance_tracer = false use_starscan = false + use_full_mte = false } # enable_backup_ref_ptr_slow_checks can only be used if @@ -276,6 +288,11 @@ assert( enable_backup_ref_ptr_support || !enable_dangling_raw_ptr_checks, "Can't enable dangling raw_ptr checks if BackupRefPtr isn't enabled at all") +# It's meaningless to force on DPD (e.g. on bots) if the support isn't compiled +# in. +assert(enable_dangling_raw_ptr_checks || !enable_dangling_raw_ptr_feature_flag, + "Meaningless to enable DPD without it compiled.") + # To run the dangling raw_ptr detector experiment, the underlying feature must # be enabled too. assert( @@ -336,6 +353,11 @@ assert(build_with_chromium || !use_asan_backup_ref_ptr, assert(!use_asan_backup_ref_ptr || use_hookable_raw_ptr, "AsanBackupRefPtr requires RawPtrHookableImpl") +# use_full_mte can only be used if has_memory_tagging is true. +assert( + has_memory_tagging || !use_full_mte, + "Can't use full MTE protection if memory tagging isn't supported at all.") + declare_args() { # pkeys support is explicitly disabled in all Cronet builds, as some test # dependencies that use partition_allocator are compiled in AOSP against a diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn index 4c0241f1b0..ec38e689c7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/BUILD.gn @@ -200,6 +200,8 @@ buildflag_header("partition_alloc_buildflags") { "FORCE_ENABLE_RAW_PTR_EXCLUSION=$force_enable_raw_ptr_exclusion", + "USE_FULL_MTE=use_full_mte", + "RECORD_ALLOC_INFO=$_record_alloc_info", "USE_FREESLOT_BITMAP=$use_freeslot_bitmap", "GLUE_CORE_POOLS=$_glue_core_pools", @@ -337,7 +339,7 @@ if (is_clang_or_gcc) { # This is already set when we compile libc++, see # buildtools/third_party/libc++/BUILD.gn. But it needs to be set here as # well, since the shim defines the symbols, to prevent them being exported. - cflags = [ "-fvisibility-global-new-delete-hidden" ] + cflags = [ "-fvisibility-global-new-delete=force-hidden" ] } } @@ -799,13 +801,17 @@ if (is_clang_or_gcc) { shim_headers = [] shim_sources = [] - shim_sources += [ "shim/allocator_shim.cc" ] + shim_sources += [ + "shim/allocator_shim.cc", + "shim/allocator_shim_dispatch_to_noop_on_free.cc", + ] shim_headers += [ "shim/allocator_shim.h", "shim/allocator_shim_internals.h", "shim/shim_alloc_functions.h", "shim/allocator_shim_functions.h", "shim/allocator_dispatch.h", + "shim/allocator_shim_dispatch_to_noop_on_free.h", ] if (use_partition_alloc) { shim_sources += [ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h index 45fec29f8c..b31a145ff6 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/internal_allocator_forward.h @@ -27,11 +27,24 @@ PartitionRoot& InternalAllocatorRoot(); template class InternalAllocator { public: - // Member types required by allocator completeness requirements. using value_type = T; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; - using propagate_on_container_move_assignment = std::true_type; + using is_always_equal = std::true_type; + + InternalAllocator() = default; + + template + InternalAllocator(const InternalAllocator&) {} // NOLINT + + template + InternalAllocator& operator=(const InternalAllocator&) { + return *this; + } + + template + bool operator==(const InternalAllocator&) { + // InternalAllocator can free allocations made by InternalAllocator. + return true; + } value_type* allocate(std::size_t count); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc index 2fed01eb2a..537304fbb0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc @@ -11,43 +11,26 @@ namespace partition_alloc::internal { LightweightQuarantineBranch LightweightQuarantineRoot::CreateBranch( - size_t quarantine_capacity_count, bool lock_required) { - return LightweightQuarantineBranch(*this, quarantine_capacity_count, - lock_required); + return LightweightQuarantineBranch(*this, lock_required); } -LightweightQuarantineBranch::LightweightQuarantineBranch( - Root& root, - size_t quarantine_capacity_count, - bool lock_required) - : root_(root), - quarantine_capacity_count_(quarantine_capacity_count), - lock_required_(lock_required), - slots_(static_cast( - InternalAllocatorRoot().Alloc( - sizeof(QuarantineSlot) * quarantine_capacity_count))) { - // `QuarantineCapacityCount` must be a positive number. - PA_CHECK(0 < quarantine_capacity_count); -} +LightweightQuarantineBranch::LightweightQuarantineBranch(Root& root, + bool lock_required) + : root_(root), lock_required_(lock_required) {} LightweightQuarantineBranch::LightweightQuarantineBranch( LightweightQuarantineBranch&& b) : root_(b.root_), - quarantine_capacity_count_(b.quarantine_capacity_count_), lock_required_(b.lock_required_), - slots_(b.slots_), - branch_count_(b.branch_count_), + slots_(std::move(b.slots_)), branch_size_in_bytes_(b.branch_size_in_bytes_) { - b.slots_ = nullptr; - b.branch_count_ = 0; b.branch_size_in_bytes_ = 0; } LightweightQuarantineBranch::~LightweightQuarantineBranch() { Purge(); - InternalAllocatorRoot().Free(slots_); - slots_ = nullptr; + slots_.clear(); } bool LightweightQuarantineBranch::Quarantine(void* object, @@ -73,24 +56,18 @@ bool LightweightQuarantineBranch::Quarantine(void* object, } // Dequarantine some entries as required. - PurgeInternal(quarantine_capacity_count_ - 1, - capacity_in_bytes - usable_size); + PurgeInternal(capacity_in_bytes - usable_size); // Update stats (locked). - branch_count_++; - PA_DCHECK(branch_count_ <= quarantine_capacity_count_); branch_size_in_bytes_ += usable_size; PA_DCHECK(branch_size_in_bytes_ <= capacity_in_bytes); - slots_[branch_count_ - 1] = { - .object = object, - .usable_size = usable_size, - }; + slots_.emplace_back(slot_start, usable_size); // Swap randomly so that the quarantine list remain shuffled. // This is not uniformly random, but sufficiently random. - const size_t random_index = random_.RandUint32() % branch_count_; - std::swap(slots_[random_index], slots_[branch_count_ - 1]); + const size_t random_index = random_.RandUint32() % slots_.size(); + std::swap(slots_[random_index], slots_.back()); } // Update stats (not locked). @@ -102,34 +79,42 @@ bool LightweightQuarantineBranch::Quarantine(void* object, return true; } -void LightweightQuarantineBranch::PurgeInternal(size_t target_branch_count, - size_t target_size_in_bytes) { +bool LightweightQuarantineBranch::IsQuarantinedForTesting(void* object) { + ConditionalScopedGuard guard(lock_required_, lock_); + uintptr_t slot_start = root_.allocator_root_.ObjectToSlotStart(object); + for (const auto& slot : slots_) { + if (slot.slot_start == slot_start) { + return true; + } + } + return false; +} + +void LightweightQuarantineBranch::PurgeInternal(size_t target_size_in_bytes) { size_t size_in_bytes = root_.size_in_bytes_.load(std::memory_order_acquire); int64_t freed_count = 0; int64_t freed_size_in_bytes = 0; // Dequarantine some entries as required. - while (branch_count_ && (target_branch_count < branch_count_ || - target_size_in_bytes < size_in_bytes)) { + while (!slots_.empty() && target_size_in_bytes < size_in_bytes) { // As quarantined entries are shuffled, picking last entry is equivalent // to picking random entry. - const auto& to_free = slots_[branch_count_ - 1]; + const auto& to_free = slots_.back(); size_t to_free_size = to_free.usable_size; - auto* slot_span = SlotSpanMetadata::FromObject(to_free.object); - uintptr_t slot_start = - root_.allocator_root_.ObjectToSlotStart(to_free.object); - PA_DCHECK(slot_span == SlotSpanMetadata::FromSlotStart(slot_start)); + auto* slot_span = SlotSpanMetadata::FromSlotStart(to_free.slot_start); + void* object = root_.allocator_root_.SlotStartToObject(to_free.slot_start); + PA_DCHECK(slot_span == SlotSpanMetadata::FromObject(object)); - PA_DCHECK(to_free.object); - root_.allocator_root_.FreeNoHooksImmediate(to_free.object, slot_span, - slot_start); + PA_DCHECK(to_free.slot_start); + root_.allocator_root_.FreeNoHooksImmediate(object, slot_span, + to_free.slot_start); freed_count++; freed_size_in_bytes += to_free_size; - - branch_count_--; size_in_bytes -= to_free_size; + + slots_.pop_back(); } branch_size_in_bytes_ -= freed_size_in_bytes; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h index f1a9c58743..aebff11490 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h @@ -39,7 +39,9 @@ #include #include #include +#include +#include "partition_alloc/internal_allocator_forward.h" #include "partition_alloc/partition_alloc_base/component_export.h" #include "partition_alloc/partition_alloc_base/rand_util.h" #include "partition_alloc/partition_alloc_base/thread_annotations.h" @@ -63,8 +65,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LightweightQuarantineRoot { : allocator_root_(allocator_root), capacity_in_bytes_(capacity_in_bytes) {} - LightweightQuarantineBranch CreateBranch(size_t quarantine_capacity_count, - bool lock_required = true); + LightweightQuarantineBranch CreateBranch(bool lock_required = true); void AccumulateStats(LightweightQuarantineStats& stats) const { stats.count += count_.load(std::memory_order_relaxed); @@ -122,38 +123,26 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LightweightQuarantineBranch { // It is possible that another branch with entries and it remains untouched. void Purge() { ConditionalScopedGuard guard(lock_required_, lock_); - PurgeInternal(0, 0); + PurgeInternal(0); } // Determines this list contains an object. - bool IsQuarantinedForTesting(void* object) { - ConditionalScopedGuard guard(lock_required_, lock_); - for (size_t i = 0; i < branch_count_; i++) { - if (slots_[i].object == object) { - return true; - } - } - return false; - } + bool IsQuarantinedForTesting(void* object); Root& GetRoot() { return root_; } private: - LightweightQuarantineBranch(Root& root, - size_t quarantine_capacity_count, - bool lock_required); + LightweightQuarantineBranch(Root& root, bool lock_required); // Try to dequarantine entries to satisfy below: - // branch_count_ <= target_branch_count - // && root_.size_in_bytes_ <= target_size_in_bytes + // root_.size_in_bytes_ <= target_size_in_bytes // It is possible that this branch cannot satisfy the // request as it has control over only what it has. If you need to ensure the // constraint, call `Purge()` for each branch in sequence, synchronously. - void PurgeInternal(size_t target_branch_count, size_t target_size_in_bytes) + void PurgeInternal(size_t target_size_in_bytes) PA_EXCLUSIVE_LOCKS_REQUIRED(lock_); Root& root_; - const size_t quarantine_capacity_count_; bool lock_required_; Lock lock_; @@ -183,17 +172,13 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) LightweightQuarantineBranch { // Thread-unsafe so guarded by `lock_`. base::InsecureRandomGenerator random_ PA_GUARDED_BY(lock_); - // `slots_` hold an array of quarantined entries. - // The contents of empty slots are undefined and reads should not occur. - // First `branch_count_` slots are used and entries should be shuffled. + // `slots_` hold quarantined entries. struct QuarantineSlot { - void* object; + uintptr_t slot_start; size_t usable_size; }; - QuarantineSlot* slots_ PA_GUARDED_BY(lock_); - - // # of quarantined entries in this branch. - size_t branch_count_ PA_GUARDED_BY(lock_) = 0; + std::vector> slots_ + PA_GUARDED_BY(lock_); size_t branch_size_in_bytes_ PA_GUARDED_BY(lock_) = 0; friend class LightweightQuarantineRoot; diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc index 9d66f0c754..7053f69e5d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc @@ -1,13 +1,13 @@ // 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 +#include "build/build_config.h" #include "partition_alloc/page_allocator.h" #include "partition_alloc/partition_alloc_base/cpu.h" #include "partition_alloc/partition_alloc_base/notreached.h" -#include - // PA_PROT_BTI requests a page that supports BTI landing pads. #define PA_PROT_BTI 0x10 diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h index e8e2d78b4c..7ecc64a8c0 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.h @@ -11,22 +11,6 @@ namespace partition_alloc::internal::base::ios { -// Returns whether the operating system is iOS 12 or later. -// TODO(crbug.com/1129482): Remove once minimum supported version is at least 12 -PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) bool IsRunningOnIOS12OrLater(); - -// Returns whether the operating system is iOS 13 or later. -// TODO(crbug.com/1129483): Remove once minimum supported version is at least 13 -PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) bool IsRunningOnIOS13OrLater(); - -// Returns whether the operating system is iOS 14 or later. -// TODO(crbug.com/1129484): Remove once minimum supported version is at least 14 -PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) bool IsRunningOnIOS14OrLater(); - -// Returns whether the operating system is iOS 15 or later. -// TODO(crbug.com/1227419): Remove once minimum supported version is at least 15 -PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) bool IsRunningOnIOS15OrLater(); - // Returns whether the operating system is at the given version or later. PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) bool IsRunningOnOrLater(int32_t major, int32_t minor, int32_t bug_fix); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm index 499b892f35..bd89dc2ad8 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/ios/ios_util.mm @@ -10,26 +10,6 @@ namespace partition_alloc::internal::base::ios { -bool IsRunningOnIOS12OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(12, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS13OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(13, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS14OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(14, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS15OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(15, 0, 0); - return is_running_on_or_later; -} - bool IsRunningOnOrLater(int32_t major, int32_t minor, int32_t bug_fix) { static const class OSVersion { public: diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc index 8bbff1c656..ba9426eb5e 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/ref_counted.cc @@ -8,6 +8,7 @@ #include #include +#include "build/build_config.h" #include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h" namespace partition_alloc::internal::base::subtle { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_ref_count.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_ref_count.h index 305a519b5e..86c229b494 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_ref_count.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_ref_count.h @@ -461,10 +461,15 @@ PA_ALWAYS_INLINE PartitionRefCount* PartitionRefCountPointer( #if BUILDFLAG(PA_DCHECK_IS_ON) || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) PA_CHECK(refcount_address % alignof(PartitionRefCount) == 0); #endif - // No need to tag because the ref-count is not protected by MTE. - return reinterpret_cast(refcount_address); + // In theory, no need to MTE-tag in the "previous slot" mode, because + // ref-count isn't protected by MTE. But it doesn't hurt to do so, and helps + // us avoid a branch (plus, can't easily #include partition_root.h here, due + // to cyclic dependencies). + // TODO(bartekn): Plumb the tag from the callers, so that it can be included + // in the calculations, and not re-read from memory. + return static_cast(TagAddr(refcount_address)); } else { - // No need to tag, as the metadata region isn't protected by MTE. + // No need to MTE-tag, as the metadata region isn't protected by MTE. PartitionRefCount* table_base = reinterpret_cast( (slot_start & kSuperPageBaseMask) + SystemPageSize() * 2); size_t index = ((slot_start & kSuperPageOffsetMask) >> SystemPageShift()) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc index 95efd23abe..9adb56c533 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc @@ -993,13 +993,10 @@ void PartitionRoot::Init(PartitionOptions opts) { if (settings.scheduler_loop_quarantine) { scheduler_loop_quarantine_capacity_in_bytes = opts.scheduler_loop_quarantine_capacity_in_bytes; - scheduler_loop_quarantine_capacity_count = - opts.scheduler_loop_quarantine_capacity_count; scheduler_loop_quarantine_root.SetCapacityInBytes( opts.scheduler_loop_quarantine_capacity_in_bytes); scheduler_loop_quarantine.emplace( - scheduler_loop_quarantine_root.CreateBranch( - opts.scheduler_loop_quarantine_capacity_count)); + scheduler_loop_quarantine_root.CreateBranch()); } else { // Deleting a running quarantine is not supported. PA_CHECK(!scheduler_loop_quarantine.has_value()); @@ -1044,9 +1041,11 @@ void PartitionRoot::Init(PartitionOptions opts) { size_t ref_count_size = internal::kPartitionRefCountSizeAdjustment; ref_count_size = internal::AlignUpRefCountSizeForMac(ref_count_size); #if PA_CONFIG(MAYBE_INCREASE_REF_COUNT_SIZE_FOR_MTE) - // Note the brp_enabled() check above. - // TODO(bartekn): Don't increase ref-count size in the "same slot" mode. - if (IsMemoryTaggingEnabled()) { + // When MTE is enabled together with BRP (crbug.com/1445816) in the + // "previous slot" mode (note the brp_enabled() check above), there is a + // race that can be avoided by making ref-count a multiple of the MTE + // granule and not tagging it. + if (IsMemoryTaggingEnabled() && !ref_count_in_same_slot_) { ref_count_size = internal::base::bits::AlignUp( ref_count_size, internal::kMemTagGranuleSize); } @@ -1674,8 +1673,7 @@ ThreadCache* PartitionRoot::MaybeInitThreadCache() { internal::LightweightQuarantineBranch PartitionRoot::CreateSchedulerLoopQuarantineBranch(bool lock_required) { - return scheduler_loop_quarantine_root.CreateBranch( - scheduler_loop_quarantine_capacity_count, lock_required); + return scheduler_loop_quarantine_root.CreateBranch(lock_required); } // static diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h index 1d493098e4..529bc5eac3 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/partition_root.h @@ -173,7 +173,6 @@ struct PartitionOptions { AllowToggle use_configurable_pool = kDisallowed; EnableToggle scheduler_loop_quarantine = kDisabled; - size_t scheduler_loop_quarantine_capacity_count = 0; size_t scheduler_loop_quarantine_capacity_in_bytes = 0; EnableToggle zapping_by_free_flags = kDisabled; @@ -375,7 +374,6 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { bool quarantine_always_for_testing = false; - size_t scheduler_loop_quarantine_capacity_count = 0; size_t scheduler_loop_quarantine_capacity_in_bytes = 0; internal::LightweightQuarantineRoot scheduler_loop_quarantine_root; // NoDestructor because we don't need to dequarantine objects as the root @@ -900,25 +898,45 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot { #if BUILDFLAG(PA_DCHECK_IS_ON) if (brp_enabled()) { PA_DCHECK(settings.ref_count_size > 0); - PA_DCHECK((settings.ref_count_size % internal::kMemTagGranuleSize) == 0); + if (!ref_count_in_same_slot_) { + PA_DCHECK((settings.ref_count_size % internal::kMemTagGranuleSize) == + 0); + } } else { PA_DCHECK(settings.ref_count_size == 0); } #endif // BUILDFLAG(PA_DCHECK_IS_ON) - // TODO(bartekn): Don't subtract ref-count size in the "same slot" mode. - return slot_size - settings.ref_count_size; + // Subtract ref-count size in the "previous slot" mode to avoid the MTE/BRP + // race (crbug.com/1445816). + return slot_size - (ref_count_in_same_slot_ ? 0 : settings.ref_count_size); #else // PA_CONFIG(MAYBE_INCREASE_REF_COUNT_SIZE_FOR_MTE) return slot_size; #endif } #endif // BUILDFLAG(HAS_MEMORY_TAGGING) + PA_ALWAYS_INLINE size_t ref_count_size() { +#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) + return settings.ref_count_size; +#else + return 0; +#endif + } + static void SetBrpRefCountInSameSlot(bool ref_count_in_same_slot) { #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ref_count_in_same_slot_ = ref_count_in_same_slot; #endif } + static bool GetBrpRefCountInSameSlot() { +#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) + return ref_count_in_same_slot_; +#else + return false; +#endif + } + private: static inline StraightenLargerSlotSpanFreeListsMode straighten_larger_slot_span_free_lists_ = @@ -1236,7 +1254,7 @@ PA_ALWAYS_INLINE void PartitionAllocFreeForRefCounting(uintptr_t slot_start) { // TODO(crbug.com/1511221): Memset entire slot in the "same slot" mode. // Ref-count isn't used once the slot is freed. DebugMemset(SlotStartAddr2Ptr(slot_start), kFreedByte, - slot_span->GetUtilizedSlotSize() - kInSlotRefCountBufferSize); + slot_span->GetUtilizedSlotSize() - root->ref_count_size()); #endif // BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) root->total_size_of_brp_quarantined_bytes.fetch_sub( @@ -1520,8 +1538,8 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeInline(void* object) { if (settings.scheduler_loop_quarantine) { GetSchedulerLoopQuarantineBranch().Quarantine(object, slot_span, slot_start); + return; } - return; } #if BUILDFLAG(USE_STARSCAN) @@ -1628,9 +1646,9 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( #if BUILDFLAG(PA_EXPENSIVE_DCHECKS_ARE_ON) // TODO(crbug.com/1511221): Memset entire slot in the "same slot" mode. // Ref-count isn't used once the slot is freed. - internal::DebugMemset( - internal::SlotStartAddr2Ptr(slot_start), internal::kFreedByte, - slot_span->GetUtilizedSlotSize() - internal::kInSlotRefCountBufferSize); + internal::DebugMemset(internal::SlotStartAddr2Ptr(slot_start), + internal::kFreedByte, + slot_span->GetUtilizedSlotSize() - ref_count_size()); #elif PA_CONFIG(ZERO_RANDOMLY_ON_FREE) // `memset` only once in a while: we're trading off safety for time // efficiency. @@ -1638,9 +1656,8 @@ PA_ALWAYS_INLINE void PartitionRoot::FreeNoHooksImmediate( !IsDirectMappedBucket(slot_span->bucket)) { // TODO(crbug.com/1511221): Memset entire slot in the "same slot" mode. // Ref-count isn't used once the slot is freed. - internal::SecureMemset( - internal::SlotStartAddr2Ptr(slot_start), 0, - slot_span->GetUtilizedSlotSize() - internal::kInSlotRefCountBufferSize); + internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start), 0, + slot_span->GetUtilizedSlotSize() - ref_count_size()); } #endif // PA_CONFIG(ZERO_RANDOMLY_ON_FREE) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc index 9b18b557a8..0e85768422 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.cc @@ -24,12 +24,14 @@ static_assert(BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT), namespace { struct Info { - explicit Info(uintptr_t slot_count) : slot_count(slot_count) { + explicit Info(uintptr_t slot_count, bool may_dangle) + : slot_count(slot_count), may_dangle(may_dangle) { partition_alloc::internal::base::debug::CollectStackTrace( stack_trace.data(), stack_trace.size()); } uintptr_t slot_count; + bool may_dangle; std::array stack_trace = {}; }; @@ -49,7 +51,9 @@ auto& GetStorageMutex() { std::atomic InstanceTracer::counter_ = 0; -void InstanceTracer::TraceImpl(uint64_t owner_id, uintptr_t address) { +void InstanceTracer::TraceImpl(uint64_t owner_id, + bool may_dangle, + uintptr_t address) { PA_CHECK(owner_id); const std::pair slot_and_size = partition_alloc::PartitionAllocGetSlotStartAndSizeInBRPPool(address); @@ -58,7 +62,7 @@ void InstanceTracer::TraceImpl(uint64_t owner_id, uintptr_t address) { slot_and_size.first, slot_and_size.second)); const std::lock_guard guard(GetStorageMutex()); - GetStorage().insert({owner_id, Info(slot_count)}); + GetStorage().insert({owner_id, Info(slot_count, may_dangle)}); } void InstanceTracer::UntraceImpl(uint64_t owner_id) { @@ -72,7 +76,7 @@ InstanceTracer::GetStackTracesForDanglingRefs(uintptr_t allocation) { std::vector> result; const std::lock_guard guard(GetStorageMutex()); for (const auto& [id, info] : GetStorage()) { - if (info.slot_count == allocation) { + if (info.slot_count == allocation && !info.may_dangle) { result.push_back(info.stack_trace); } } diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h index b2b01b8dc7..ffcce58690 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/instance_tracer.h @@ -26,8 +26,9 @@ class InstanceTracer { public: constexpr uint64_t owner_id() const { return 0; } - constexpr static void Trace(uint64_t owner_id, uintptr_t address) {} - constexpr static void Untrace(uint64_t owner_id) {} + constexpr static void Trace([[maybe_unused]] uint64_t owner_id, + [[maybe_unused]] uintptr_t address) {} + constexpr static void Untrace([[maybe_unused]] uint64_t owner_id) {} }; #else @@ -48,12 +49,14 @@ class PA_TRIVIAL_ABI InstanceTracer { constexpr uint64_t owner_id() const { return owner_id_; } - constexpr static void Trace(uint64_t owner_id, uintptr_t address) { + constexpr static void Trace(uint64_t owner_id, + bool may_dangle, + uintptr_t address) { if (partition_alloc::internal::base::is_constant_evaluated() || owner_id == 0) { return; } - TraceImpl(owner_id, address); + TraceImpl(owner_id, may_dangle, address); } constexpr static void Untrace(uint64_t owner_id) { if (partition_alloc::internal::base::is_constant_evaluated() || @@ -73,7 +76,7 @@ class PA_TRIVIAL_ABI InstanceTracer { private: PA_COMPONENT_EXPORT(RAW_PTR) - static void TraceImpl(uint64_t owner_id, uintptr_t address); + static void TraceImpl(uint64_t owner_id, bool may_dangle, uintptr_t address); PA_COMPONENT_EXPORT(RAW_PTR) static void UntraceImpl(uint64_t owner_id); constexpr uint64_t CreateOwnerId() { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h index eb24bea7df..c8869cf471 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h @@ -248,7 +248,7 @@ template using UnderlyingImplForTraits = internal::RawPtrNoOpImpl; #endif -constexpr bool IsPtrArithmeticAllowed(RawPtrTraits Traits) { +constexpr bool IsPtrArithmeticAllowed([[maybe_unused]] RawPtrTraits Traits) { #if BUILDFLAG(ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK) return partition_alloc::internal::ContainsFlags( Traits, RawPtrTraits::kAllowPtrArithmetic); @@ -1047,12 +1047,13 @@ using base::raw_ptr; // // When using it, please provide a justification about what guarantees that it // will never be dereferenced after becoming dangling. -constexpr auto DisableDanglingPtrDetection = base::RawPtrTraits::kMayDangle; +constexpr inline auto DisableDanglingPtrDetection = + base::RawPtrTraits::kMayDangle; // See `docs/dangling_ptr.md` // Annotates known dangling raw_ptr. Those haven't been triaged yet. All the // occurrences are meant to be removed. See https://crbug.com/1291138. -constexpr auto DanglingUntriaged = base::RawPtrTraits::kMayDangle; +constexpr inline auto DanglingUntriaged = base::RawPtrTraits::kMayDangle; // Unlike DanglingUntriaged, this annotates raw_ptrs that are known to // dangle only occasionally on the CQ. @@ -1061,18 +1062,20 @@ constexpr auto DanglingUntriaged = base::RawPtrTraits::kMayDangle; // https://docs.google.com/spreadsheets/d/1k12PQOG4y1-UEV9xDfP1F8FSk4cVFywafEYHmzFubJ8/ // // This is not meant to be added manually. You can ignore this flag. -constexpr auto FlakyDanglingUntriaged = base::RawPtrTraits::kMayDangle; +constexpr inline auto FlakyDanglingUntriaged = base::RawPtrTraits::kMayDangle; // Dangling raw_ptr that is more likely to cause UAF: its memory was freed in // one task, and the raw_ptr was released in a different one. // // This is not meant to be added manually. You can ignore this flag. -constexpr auto AcrossTasksDanglingUntriaged = base::RawPtrTraits::kMayDangle; +constexpr inline auto AcrossTasksDanglingUntriaged = + base::RawPtrTraits::kMayDangle; // The use of pointer arithmetic with raw_ptr is strongly discouraged and // disabled by default. Usually a container like span<> should be used // instead of the raw_ptr. -constexpr auto AllowPtrArithmetic = base::RawPtrTraits::kAllowPtrArithmetic; +constexpr inline auto AllowPtrArithmetic = + base::RawPtrTraits::kAllowPtrArithmetic; // The use of uninitialized pointers is strongly discouraged. raw_ptrs will // be initialized to nullptr by default in all cases when building against @@ -1084,7 +1087,8 @@ constexpr auto AllowPtrArithmetic = base::RawPtrTraits::kAllowPtrArithmetic; // Note that opting out may not always be effective, given that algorithms // like BackupRefPtr require nullptr initializaion for correctness and thus // silently enforce it. -constexpr auto AllowUninitialized = base::RawPtrTraits::kAllowUninitialized; +constexpr inline auto AllowUninitialized = + base::RawPtrTraits::kAllowUninitialized; // This flag is used to tag a subset of dangling pointers. Similarly to // DanglingUntriaged, those pointers are known to be dangling. However, we also @@ -1093,23 +1097,33 @@ constexpr auto AllowUninitialized = base::RawPtrTraits::kAllowUninitialized; // pressure on the BRP quarantine. // // This is not meant to be added manually. You can ignore this flag. -constexpr auto LeakedDanglingUntriaged = base::RawPtrTraits::kMayDangle; +constexpr inline auto LeakedDanglingUntriaged = base::RawPtrTraits::kMayDangle; // Temporary annotation for new pointers added during the renderer rewrite. // TODO(crbug.com/1444624): Find pre-existing dangling pointers and remove // this annotation. // // DO NOT ADD new occurrences of this. -constexpr auto ExperimentalRenderer = base::RawPtrTraits::kMayDangle; +constexpr inline auto ExperimentalRenderer = base::RawPtrTraits::kMayDangle; // Temporary introduced alias in the context of rewriting std::vector into // std::vector> and in order to temporarily bypass the dangling ptr // checks on the CQ. This alias will be removed gradually after the cl lands and // will be replaced by DanglingUntriaged where necessary. -// Update: The alias now temporarily disables BRP. This is due to performance -// issues. BRP will be re-enabled once the issues are identified and handled. constexpr inline auto VectorExperimental = base::RawPtrTraits::kMayDangle; +// Temporary alias introduced in the context of rewriting std::set into +// std::set> and in order to temporarily bypass the dangling ptr +// checks on the CQ. This alias will be removed gradually after the rewrite cl +// lands and will be replaced by DanglingUntriaged where necessary. +constexpr inline auto SetExperimental = base::RawPtrTraits::kMayDangle; + +// Temporary alias introduced in the context of rewriting more containers and in +// order to temporarily bypass the dangling ptr checks on the CQ. This alias +// will be removed gradually after the rewrite cl lands and will be replaced by +// DanglingUntriaged where necessary. +constexpr inline auto CtnExperimental = base::RawPtrTraits::kMayDangle; + // Temporary workaround needed when using vector // in Mocked method signatures as the macros don't allow commas within. template @@ -1150,6 +1164,15 @@ struct less> { } }; +template +struct hash> { + typedef raw_ptr argument_type; + typedef std::size_t result_type; + result_type operator()(argument_type const& ptr) const { + return hash()(ptr.get()); + } +}; + // Define for cases where raw_ptr holds a pointer to an array of type T. // This is consistent with definition of std::iterator_traits. // Algorithms like std::binary_search need that. diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h index 3d3185ef4e..c89ecc12a7 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_backup_ref_impl.h @@ -219,7 +219,7 @@ struct RawPtrBackupRefImpl { uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr); if (IsSupportedAndNotNull(address)) { PA_BASE_CHECK(wrapped_ptr != nullptr); - PA_BASE_CHECK(IsPointeeAlive(address)); + PA_BASE_CHECK(IsPointeeAlive(address)); // Detects use-after-free. } #endif // BUILDFLAG(PA_DCHECK_IS_ON) || // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -436,7 +436,7 @@ struct RawPtrBackupRefImpl { return; } - InstanceTracer::Trace(owner_id, address); + InstanceTracer::Trace(owner_id, AllowDangling, address); } static constexpr void Untrace(uint64_t owner_id) { diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h index ec74be9f59..82ae2e9765 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_noop_impl.h @@ -109,8 +109,9 @@ struct RawPtrNoOpImpl { } template - static constexpr void Trace(uint64_t owner_id, T* wrapped_ptr) {} - static constexpr void Untrace(uint64_t owner_id) {} + static constexpr void Trace([[maybe_unused]] uint64_t owner_id, + [[maybe_unused]] T* wrapped_ptr) {} + static constexpr void Untrace([[maybe_unused]] uint64_t owner_id) {} // This is for accounting only, used by unit tests. PA_ALWAYS_INLINE static constexpr void IncrementSwapCountForTest() {} diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h index 2516f4cd30..f72ad10c6d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h @@ -123,7 +123,6 @@ void ConfigurePartitions( BucketDistribution distribution, SchedulerLoopQuarantine scheduler_loop_quarantine, size_t scheduler_loop_quarantine_capacity_in_bytes, - size_t scheduler_loop_quarantine_capacity_count, ZappingByFreeFlags zapping_by_free_flags); PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) uint32_t GetMainPartitionRootExtrasSize(); diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc index 66142253ac..c47c133c1d 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc @@ -493,7 +493,6 @@ void ConfigurePartitions( BucketDistribution distribution, SchedulerLoopQuarantine scheduler_loop_quarantine, size_t scheduler_loop_quarantine_capacity_in_bytes, - size_t scheduler_loop_quarantine_capacity_count, ZappingByFreeFlags zapping_by_free_flags) { // Calling Get() is actually important, even if the return value isn't // used, because it has a side effect of initializing the variable, if it @@ -528,8 +527,6 @@ void ConfigurePartitions( : partition_alloc::PartitionOptions::kDisabled; opts.scheduler_loop_quarantine_capacity_in_bytes = scheduler_loop_quarantine_capacity_in_bytes; - opts.scheduler_loop_quarantine_capacity_count = - scheduler_loop_quarantine_capacity_count; opts.memory_tagging = { .enabled = enable_memory_tagging ? partition_alloc::PartitionOptions::kEnabled diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h index c742f68b46..6bcd8faf69 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h @@ -95,14 +95,12 @@ PA_ALWAYS_INLINE void ConfigurePartitionsForTesting() { auto distribution = BucketDistribution::kNeutral; auto scheduler_loop_quarantine = SchedulerLoopQuarantine(false); size_t scheduler_loop_quarantine_capacity_in_bytes = 0; - size_t scheduler_loop_quarantine_capacity_count = 0; auto zapping_by_free_flags = ZappingByFreeFlags(false); ConfigurePartitions( enable_brp, enable_memory_tagging, memory_tagging_reporting_mode, distribution, scheduler_loop_quarantine, - scheduler_loop_quarantine_capacity_in_bytes, - scheduler_loop_quarantine_capacity_count, zapping_by_free_flags); + scheduler_loop_quarantine_capacity_in_bytes, zapping_by_free_flags); } #endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc new file mode 100644 index 0000000000..2f3cd35bf3 --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.cc @@ -0,0 +1,138 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h" + +#include + +#include "partition_alloc/partition_alloc_check.h" +#include "partition_alloc/shim/allocator_dispatch.h" +#include "partition_alloc/shim/allocator_shim.h" + +namespace allocator_shim { +namespace { +void* AllocFn(const AllocatorDispatch* self, size_t size, void* context) { + return self->next->alloc_function(self->next, size, context); +} + +void* AllocUncheckedFn(const AllocatorDispatch* self, + size_t size, + void* context) { + return self->next->alloc_unchecked_function(self->next, size, context); +} + +void* AllocZeroInitializedFn(const AllocatorDispatch* self, + size_t n, + size_t size, + void* context) { + return self->next->alloc_zero_initialized_function(self->next, n, size, + context); +} + +void* AllocAlignedFn(const AllocatorDispatch* self, + size_t alignment, + size_t size, + void* context) { + return self->next->alloc_aligned_function(self->next, alignment, size, + context); +} + +void* ReallocFn(const AllocatorDispatch* self, + void* address, + size_t size, + void* context) { + return self->next->realloc_function(self->next, address, size, context); +} + +void FreeFn(const AllocatorDispatch* self, void* address, void* context) {} + +size_t GetSizeEstimateFn(const AllocatorDispatch* self, + void* address, + void* context) { + return self->next->get_size_estimate_function(self->next, address, context); +} + +size_t GoodSizeFn(const AllocatorDispatch* self, size_t size, void* context) { + return self->next->good_size_function(self->next, size, context); +} + +bool ClaimedAddressFn(const AllocatorDispatch* self, + void* address, + void* context) { + return self->next->claimed_address_function(self->next, address, context); +} + +unsigned BatchMallocFn(const AllocatorDispatch* self, + size_t size, + void** results, + unsigned num_requested, + void* context) { + return self->next->batch_malloc_function(self->next, size, results, + num_requested, context); +} + +void BatchFreeFn(const AllocatorDispatch* self, + void** to_be_freed, + unsigned num_to_be_freed, + void* context) {} + +void FreeDefiniteSizeFn(const AllocatorDispatch* self, + void* address, + size_t size, + void* context) {} + +void TryFreeDefaultFn(const AllocatorDispatch* self, + void* address, + void* context) {} + +static void* AlignedMallocFn(const AllocatorDispatch* self, + size_t size, + size_t alignment, + void* context) { + return self->next->aligned_malloc_function(self->next, size, alignment, + context); +} + +static void* AlignedReallocFn(const AllocatorDispatch* self, + void* address, + size_t size, + size_t alignment, + void* context) { + return self->next->aligned_realloc_function(self->next, address, size, + alignment, context); +} + +static void AlignedFreeFn(const AllocatorDispatch* self, + void* address, + void* context) {} + +AllocatorDispatch allocator_dispatch = { + &AllocFn, + &AllocUncheckedFn, + &AllocZeroInitializedFn, + &AllocAlignedFn, + &ReallocFn, + &FreeFn, + &GetSizeEstimateFn, + &GoodSizeFn, + &ClaimedAddressFn, + &BatchMallocFn, + &BatchFreeFn, + &FreeDefiniteSizeFn, + &TryFreeDefaultFn, + &AlignedMallocFn, + &AlignedReallocFn, + &AlignedFreeFn, + nullptr /* next */ +}; +} // namespace + +void InsertNoOpOnFreeAllocatorShimOnShutDown() { + static bool called = false; + PA_CHECK(!called); + called = true; + InsertAllocatorDispatch(&allocator_dispatch); +} + +} // namespace allocator_shim diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h new file mode 100644 index 0000000000..9c07d9d24b --- /dev/null +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_dispatch_to_noop_on_free.h @@ -0,0 +1,18 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DISPATCH_TO_NOOP_ON_FREE_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DISPATCH_TO_NOOP_ON_FREE_H_ + +#include "partition_alloc/partition_alloc_base/component_export.h" + +namespace allocator_shim { +// Places an allocator shim layer at the front of the chain during shutdown. +// This new layer replaces free() with a no-op implementation +// in order to prevent shutdown hangs. +PA_COMPONENT_EXPORT(ALLOCATOR_SHIM) +void InsertNoOpOnFreeAllocatorShimOnShutDown(); +} // namespace allocator_shim + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_DISPATCH_TO_NOOP_ON_FREE_H_ diff --git a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h index 1ebe4bd262..bc6a2fe589 100644 --- a/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h +++ b/naiveproxy/src/base/allocator/partition_allocator/src/partition_alloc/thread_cache.h @@ -614,7 +614,7 @@ PA_ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket, // When BRP is on in the "previous slot" mode, this slot may have a BRP // ref-count of the next, potentially allocated slot. Make sure we don't // overwrite it. - // TODO(bartekn): Ok to overwriter in the "same slot" mode. + // TODO(bartekn): Ok to overwrite in the "same slot" mode. int slot_size_remaining_in_16_bytes = (bucket.slot_size - internal::kInSlotRefCountBufferSize) / 16; diff --git a/naiveproxy/src/base/android/base_jni_onload.cc b/naiveproxy/src/base/android/base_jni_onload.cc index 0b64a91e4a..3e80a5aa5e 100644 --- a/naiveproxy/src/base/android/base_jni_onload.cc +++ b/naiveproxy/src/base/android/base_jni_onload.cc @@ -14,8 +14,6 @@ namespace android { bool OnJNIOnLoadInit() { InitAtExitManager(); - JNIEnv* env = base::android::AttachCurrentThread(); - base::android::InitGlobalClassLoader(env); return true; } diff --git a/naiveproxy/src/base/android/callback_android.cc b/naiveproxy/src/base/android/callback_android.cc index b7d3b2f874..b33acbba0b 100644 --- a/naiveproxy/src/base/android/callback_android.cc +++ b/naiveproxy/src/base/android/callback_android.cc @@ -4,11 +4,13 @@ #include "base/android/callback_android.h" +#include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/base_jni/Callback_jni.h" #include "base/time/time.h" +#include "base/types/optional_ref.h" namespace base { namespace android { @@ -43,6 +45,20 @@ void RunStringCallbackAndroid(const JavaRef& callback, Java_Helper_onObjectResultFromNative(env, callback, java_string); } +void RunOptionalStringCallbackAndroid( + const JavaRef& callback, + base::optional_ref optional_string_arg) { + JNIEnv* env = AttachCurrentThread(); + if (optional_string_arg.has_value()) { + Java_Helper_onOptionalStringResultFromNative( + env, callback, true, + ConvertUTF8ToJavaString(env, optional_string_arg.value())); + } else { + Java_Helper_onOptionalStringResultFromNative( + env, callback, false, ConvertUTF8ToJavaString(env, std::string())); + } +} + void RunByteArrayCallbackAndroid(const JavaRef& callback, const std::vector& arg) { JNIEnv* env = AttachCurrentThread(); diff --git a/naiveproxy/src/base/android/callback_android.h b/naiveproxy/src/base/android/callback_android.h index fa2420c816..1165d0f5c5 100644 --- a/naiveproxy/src/base/android/callback_android.h +++ b/naiveproxy/src/base/android/callback_android.h @@ -12,6 +12,7 @@ #include "base/android/scoped_java_ref.h" #include "base/base_export.h" #include "base/time/time.h" +#include "base/types/optional_ref.h" // Provides helper utility methods that run the given callback with the // specified argument. @@ -36,6 +37,10 @@ void BASE_EXPORT RunTimeCallbackAndroid(const JavaRef& callback, void BASE_EXPORT RunStringCallbackAndroid(const JavaRef& callback, const std::string& arg); +void BASE_EXPORT RunOptionalStringCallbackAndroid( + const JavaRef& callback, + base::optional_ref optional_string_arg); + void BASE_EXPORT RunByteArrayCallbackAndroid(const JavaRef& callback, const std::vector& arg); diff --git a/naiveproxy/src/base/android/early_trace_event_binding.cc b/naiveproxy/src/base/android/early_trace_event_binding.cc index 34bab452fd..a90a8fc382 100644 --- a/naiveproxy/src/base/android/early_trace_event_binding.cc +++ b/naiveproxy/src/base/android/early_trace_event_binding.cc @@ -120,13 +120,13 @@ static void JNI_EarlyTraceEvent_RecordEarlyAsyncEndEvent(JNIEnv* env, } bool GetBackgroundStartupTracingFlag() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return base::android::Java_EarlyTraceEvent_getBackgroundStartupTracingFlag( env); } void SetBackgroundStartupTracingFlag(bool enabled) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::Java_EarlyTraceEvent_setBackgroundStartupTracingFlag(env, enabled); } diff --git a/naiveproxy/src/base/android/event_log.cc b/naiveproxy/src/base/android/event_log.cc index 66ef6ec12e..14c27447cc 100644 --- a/naiveproxy/src/base/android/event_log.cc +++ b/naiveproxy/src/base/android/event_log.cc @@ -9,7 +9,7 @@ namespace base { namespace android { void EventLogWriteInt(int tag, int value) { - Java_EventLog_writeEvent(AttachCurrentThread(), tag, value); + Java_EventLog_writeEvent(jni_zero::AttachCurrentThread(), tag, value); } } // namespace android diff --git a/naiveproxy/src/base/android/int_string_callback.cc b/naiveproxy/src/base/android/int_string_callback.cc index 06d3e32cba..f35be5f8b9 100644 --- a/naiveproxy/src/base/android/int_string_callback.cc +++ b/naiveproxy/src/base/android/int_string_callback.cc @@ -19,7 +19,7 @@ namespace android { void RunIntStringCallbackAndroid(const JavaRef& callback, int int_arg, const std::string& str_arg) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); Java_IntStringCallback_onResult(env, callback, int_arg, ConvertUTF8ToJavaString(env, str_arg)); } diff --git a/naiveproxy/src/base/android/java_heap_dump_generator.cc b/naiveproxy/src/base/android/java_heap_dump_generator.cc index 51cb7004f4..161d370e2f 100644 --- a/naiveproxy/src/base/android/java_heap_dump_generator.cc +++ b/naiveproxy/src/base/android/java_heap_dump_generator.cc @@ -13,7 +13,7 @@ namespace base { namespace android { bool WriteJavaHeapDumpToPath(base::StringPiece filePath) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return Java_JavaHeapDumpGenerator_generateHprof( env, base::android::ConvertUTF8ToJavaString(env, filePath)); } diff --git a/naiveproxy/src/base/android/java_runtime.cc b/naiveproxy/src/base/android/java_runtime.cc index c22132694b..9a76801581 100644 --- a/naiveproxy/src/base/android/java_runtime.cc +++ b/naiveproxy/src/base/android/java_runtime.cc @@ -12,7 +12,7 @@ namespace android { void JavaRuntime::GetMemoryUsage(uint64_t* total_memory, uint64_t* free_memory) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::ScopedJavaLocalRef runtime = JNI_Runtime::Java_Runtime_getRuntime(env); *total_memory = checked_cast( diff --git a/naiveproxy/src/base/android/jni_android.cc b/naiveproxy/src/base/android/jni_android.cc index f1ea3806eb..af4e0a70d0 100644 --- a/naiveproxy/src/base/android/jni_android.cc +++ b/naiveproxy/src/base/android/jni_android.cc @@ -16,8 +16,9 @@ #include "base/feature_list.h" #include "base/logging.h" #include "build/build_config.h" +#include "build/robolectric_buildflags.h" #include "third_party/abseil-cpp/absl/base/attributes.h" -#include "third_party/jni_zero/core.h" +#include "third_party/jni_zero/jni_zero.h" namespace base { namespace android { @@ -33,42 +34,39 @@ BASE_FEATURE(kHandleExceptionsInJava, "HandleJniExceptionsInJava", base::FEATURE_ENABLED_BY_DEFAULT); -jobject g_class_loader = nullptr; jclass g_out_of_memory_error_class = nullptr; + +#if !BUILDFLAG(IS_ROBOLECTRIC) jmethodID g_class_loader_load_class_method_id = nullptr; - -ScopedJavaLocalRef GetClassInternal(JNIEnv* env, - const char* class_name, - jobject class_loader) { - jclass clazz; - if (class_loader != nullptr) { - // ClassLoader.loadClass expects a classname with components separated by - // dots instead of the slashes that JNIEnv::FindClass expects. The JNI - // generator generates names with slashes, so we have to replace them here. - // TODO(torne): move to an approach where we always use ClassLoader except - // for the special case of base::android::GetClassLoader(), and change the - // JNI generator to generate dot-separated names. http://crbug.com/461773 - size_t bufsize = strlen(class_name) + 1; - char dotted_name[bufsize]; - memmove(dotted_name, class_name, bufsize); - for (size_t i = 0; i < bufsize; ++i) { - if (dotted_name[i] == '/') { - dotted_name[i] = '.'; - } - } - - clazz = static_cast( - env->CallObjectMethod(class_loader, g_class_loader_load_class_method_id, - ConvertUTF8ToJavaString(env, dotted_name).obj())); - } else { - clazz = env->FindClass(class_name); - } - if (ClearException(env) || !clazz) { - LOG(FATAL) << "Failed to find class " << class_name; - } - return ScopedJavaLocalRef(env, clazz); +// ClassLoader.loadClass() accepts either slashes or dots on Android, but JVM +// requires dots. We could translate, but there is no need to go through +// ClassLoaders in Robolectric anyways. +// https://cs.android.com/search?q=symbol:DexFile_defineClassNative +jclass GetClassFromSplit(JNIEnv* env, + const char* class_name, + const char* split_name) { + return static_cast(env->CallObjectMethod( + GetSplitClassLoader(env, split_name), g_class_loader_load_class_method_id, + ConvertUTF8ToJavaString(env, class_name).obj())); } +// Must be called before using GetClassFromSplit - we need to set the global, +// and we need to call GetClassLoader at least once to allow the default +// resolver (env->FindClass()) to get our main ClassLoader class instance, which +// we then cache use for all future calls to GetSplitClassLoader. +void PrepareClassLoaders(JNIEnv* env) { + if (g_class_loader_load_class_method_id == nullptr) { + GetClassLoader(env); + ScopedJavaLocalRef class_loader_clazz = ScopedJavaLocalRef( + env, env->FindClass("java/lang/ClassLoader")); + CHECK(!ClearException(env)); + g_class_loader_load_class_method_id = + env->GetMethodID(class_loader_clazz.obj(), "loadClass", + "(Ljava/lang/String;)Ljava/lang/Class;"); + CHECK(!ClearException(env)); + } +} +#endif // !BUILDFLAG(IS_ROBOLECTRIC) } // namespace LogFatalCallback g_log_fatal_callback_for_testing = nullptr; @@ -95,133 +93,18 @@ void InitVM(JavaVM* vm) { jni_zero::InitVM(vm); jni_zero::SetExceptionHandler(CheckException); JNIEnv* env = jni_zero::AttachCurrentThread(); +#if !BUILDFLAG(IS_ROBOLECTRIC) + // Warm-up needed for GetClassFromSplit, must be called before we set the + // resolver, since GetClassFromSplit won't work until after + // PrepareClassLoaders has happened. + PrepareClassLoaders(env); + jni_zero::SetClassResolver(GetClassFromSplit); +#endif g_out_of_memory_error_class = static_cast( env->NewGlobalRef(env->FindClass("java/lang/OutOfMemoryError"))); DCHECK(g_out_of_memory_error_class); } -void InitGlobalClassLoader(JNIEnv* env) { - DCHECK(g_class_loader == nullptr); - - ScopedJavaLocalRef class_loader_clazz = - GetClass(env, "java/lang/ClassLoader"); - CHECK(!ClearException(env)); - g_class_loader_load_class_method_id = - env->GetMethodID(class_loader_clazz.obj(), - "loadClass", - "(Ljava/lang/String;)Ljava/lang/Class;"); - CHECK(!ClearException(env)); - - // GetClassLoader() caches the reference, so we do not need to wrap it in a - // smart pointer as well. - g_class_loader = GetClassLoader(env); -} - -ScopedJavaLocalRef GetClass(JNIEnv* env, - const char* class_name, - const char* split_name) { - return GetClassInternal(env, class_name, - GetSplitClassLoader(env, split_name)); -} - -ScopedJavaLocalRef GetClass(JNIEnv* env, const char* class_name) { - return GetClassInternal(env, class_name, g_class_loader); -} - -// This is duplicated with LazyGetClass below because these are performance -// sensitive. -jclass LazyGetClass(JNIEnv* env, - const char* class_name, - const char* split_name, - std::atomic* atomic_class_id) { - const jclass value = atomic_class_id->load(std::memory_order_acquire); - if (value) - return value; - ScopedJavaGlobalRef clazz; - clazz.Reset(GetClass(env, class_name, split_name)); - jclass cas_result = nullptr; - if (atomic_class_id->compare_exchange_strong(cas_result, clazz.obj(), - std::memory_order_acq_rel)) { - // We intentionally leak the global ref since we now storing it as a raw - // pointer in |atomic_class_id|. - return clazz.Release(); - } else { - return cas_result; - } -} - -// This is duplicated with LazyGetClass above because these are performance -// sensitive. -jclass LazyGetClass(JNIEnv* env, - const char* class_name, - std::atomic* atomic_class_id) { - const jclass value = atomic_class_id->load(std::memory_order_acquire); - if (value) - return value; - ScopedJavaGlobalRef clazz; - clazz.Reset(GetClass(env, class_name)); - jclass cas_result = nullptr; - if (atomic_class_id->compare_exchange_strong(cas_result, clazz.obj(), - std::memory_order_acq_rel)) { - // We intentionally leak the global ref since we now storing it as a raw - // pointer in |atomic_class_id|. - return clazz.Release(); - } else { - return cas_result; - } -} - -template -jmethodID MethodID::Get(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature) { - auto get_method_ptr = type == MethodID::TYPE_STATIC ? - &JNIEnv::GetStaticMethodID : - &JNIEnv::GetMethodID; - jmethodID id = (env->*get_method_ptr)(clazz, method_name, jni_signature); - if (base::android::ClearException(env) || !id) { - LOG(FATAL) << "Failed to find " << - (type == TYPE_STATIC ? "static " : "") << - "method " << method_name << " " << jni_signature; - } - return id; -} - -// If |atomic_method_id| set, it'll return immediately. Otherwise, it'll call -// into ::Get() above. If there's a race, it's ok since the values are the same -// (and the duplicated effort will happen only once). -template -jmethodID MethodID::LazyGet(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature, - std::atomic* atomic_method_id) { - const jmethodID value = atomic_method_id->load(std::memory_order_acquire); - if (value) - return value; - jmethodID id = MethodID::Get(env, clazz, method_name, jni_signature); - atomic_method_id->store(id, std::memory_order_release); - return id; -} - -// Various template instantiations. -template jmethodID MethodID::Get( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature); - -template jmethodID MethodID::Get( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature); - -template jmethodID MethodID::LazyGet( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature, std::atomic* atomic_method_id); - -template jmethodID MethodID::LazyGet( - JNIEnv* env, jclass clazz, const char* method_name, - const char* jni_signature, std::atomic* atomic_method_id); - void CheckException(JNIEnv* env) { if (!jni_zero::HasException(env)) { diff --git a/naiveproxy/src/base/android/jni_android.h b/naiveproxy/src/base/android/jni_android.h index c25784b92d..428255b2dc 100644 --- a/naiveproxy/src/base/android/jni_android.h +++ b/naiveproxy/src/base/android/jni_android.h @@ -17,7 +17,7 @@ #include "base/compiler_specific.h" #include "base/debug/debugging_buildflags.h" #include "base/debug/stack_trace.h" -#include "third_party/jni_zero/core.h" +#include "third_party/jni_zero/jni_zero.h" namespace base { namespace android { @@ -81,65 +81,16 @@ inline void DisableJvmForTesting() { return jni_zero::DisableJvmForTesting(); } -// Initializes the global ClassLoader used by the GetClass and LazyGetClass -// methods. This is needed because JNI will use the base ClassLoader when there -// is no Java code on the stack. The base ClassLoader doesn't know about any of -// the application classes and will fail to lookup anything other than system -// classes. -void InitGlobalClassLoader(JNIEnv* env); - // Finds the class named |class_name| and returns it. // Use this method instead of invoking directly the JNI FindClass method (to // prevent leaking local references). // This method triggers a fatal assertion if the class could not be found. // Use HasClass if you need to check whether the class exists. -BASE_EXPORT ScopedJavaLocalRef GetClass(JNIEnv* env, - const char* class_name, - const char* split_name); -BASE_EXPORT ScopedJavaLocalRef GetClass(JNIEnv* env, - const char* class_name); +inline ScopedJavaLocalRef GetClass(JNIEnv* env, + const char* class_name) { + return jni_zero::GetClass(env, class_name); +} -// The method will initialize |atomic_class_id| to contain a global ref to the -// class. And will return that ref on subsequent calls. It's the caller's -// responsibility to release the ref when it is no longer needed. -// The caller is responsible to zero-initialize |atomic_method_id|. -// It's fine to simultaneously call this on multiple threads referencing the -// same |atomic_method_id|. -BASE_EXPORT jclass LazyGetClass(JNIEnv* env, - const char* class_name, - const char* split_name, - std::atomic* atomic_class_id); -BASE_EXPORT jclass LazyGetClass( - JNIEnv* env, - const char* class_name, - std::atomic* atomic_class_id); - -// This class is a wrapper for JNIEnv Get(Static)MethodID. -class BASE_EXPORT MethodID { - public: - enum Type { - TYPE_STATIC, - TYPE_INSTANCE, - }; - - // Returns the method ID for the method with the specified name and signature. - // This method triggers a fatal assertion if the method could not be found. - template - static jmethodID Get(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature); - - // The caller is responsible to zero-initialize |atomic_method_id|. - // It's fine to simultaneously call this on multiple threads referencing the - // same |atomic_method_id|. - template - static jmethodID LazyGet(JNIEnv* env, - jclass clazz, - const char* method_name, - const char* jni_signature, - std::atomic* atomic_method_id); -}; // Returns true if an exception is pending in the provided JNIEnv*. inline bool HasException(JNIEnv* env) { @@ -162,6 +113,7 @@ BASE_EXPORT std::string GetJavaExceptionInfo( // This returns a string representation of the java stack trace. BASE_EXPORT std::string GetJavaStackTraceIfPresent(); +using MethodID = jni_zero::MethodID; } // namespace android } // namespace base diff --git a/naiveproxy/src/base/android/jni_array.cc b/naiveproxy/src/base/android/jni_array.cc index 6690bd8163..e0add42010 100644 --- a/naiveproxy/src/base/android/jni_array.cc +++ b/naiveproxy/src/base/android/jni_array.cc @@ -34,8 +34,7 @@ ScopedJavaLocalRef ToJavaByteArray( ScopedJavaLocalRef ToJavaByteArray(JNIEnv* env, const std::string& str) { - return ToJavaByteArray(env, reinterpret_cast(str.data()), - str.size()); + return ToJavaByteArray(env, base::as_byte_span(str)); } ScopedJavaLocalRef ToJavaBooleanArray(JNIEnv* env, @@ -208,8 +207,7 @@ ScopedJavaLocalRef ToJavaArrayOfByteArray( CheckException(env); for (size_t i = 0; i < v.size(); ++i) { - ScopedJavaLocalRef byte_array = ToJavaByteArray( - env, reinterpret_cast(v[i].data()), v[i].length()); + ScopedJavaLocalRef byte_array = ToJavaByteArray(env, v[i]); env->SetObjectArrayElement(joa, static_cast(i), byte_array.obj()); } return ScopedJavaLocalRef(env, joa); @@ -224,8 +222,7 @@ ScopedJavaLocalRef ToJavaArrayOfByteArray( CheckException(env); for (size_t i = 0; i < v.size(); ++i) { - ScopedJavaLocalRef byte_array = - ToJavaByteArray(env, v[i].data(), v[i].size()); + ScopedJavaLocalRef byte_array = ToJavaByteArray(env, v[i]); env->SetObjectArrayElement(joa, static_cast(i), byte_array.obj()); } return ScopedJavaLocalRef(env, joa); diff --git a/naiveproxy/src/base/android/jni_bytebuffer.cc b/naiveproxy/src/base/android/jni_bytebuffer.cc new file mode 100644 index 0000000000..a4b9862586 --- /dev/null +++ b/naiveproxy/src/base/android/jni_bytebuffer.cc @@ -0,0 +1,47 @@ +// Copyright 2024 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/android/jni_bytebuffer.h" + +#include "base/numerics/safe_conversions.h" + +namespace base::android { + +base::span JavaByteBufferToSpan(JNIEnv* env, jobject buffer) { + auto span = MaybeJavaByteBufferToSpan(env, buffer); + CHECK(span.has_value()); + return *span; +} + +base::span JavaByteBufferToMutableSpan(JNIEnv* env, jobject buffer) { + auto span = MaybeJavaByteBufferToMutableSpan(env, buffer); + CHECK(span.has_value()); + return *span; +} + +absl::optional> MaybeJavaByteBufferToSpan( + JNIEnv* env, + jobject buffer) { + auto span = MaybeJavaByteBufferToMutableSpan(env, buffer); + return span ? absl::make_optional(base::span(*span)) + : absl::nullopt; +} + +absl::optional> MaybeJavaByteBufferToMutableSpan( + JNIEnv* env, + jobject buffer) { + void* data = env->GetDirectBufferAddress(buffer); + jlong size = env->GetDirectBufferCapacity(buffer); + + // !data && size == 0 is allowed - this is how a 0-length Buffer is + // represented. + if (size < 0 || (!data && size > 0)) { + return absl::nullopt; + } + + return base::span(static_cast(data), + base::checked_cast(size)); +} + +} // namespace base::android diff --git a/naiveproxy/src/base/android/jni_bytebuffer.h b/naiveproxy/src/base/android/jni_bytebuffer.h new file mode 100644 index 0000000000..b474713506 --- /dev/null +++ b/naiveproxy/src/base/android/jni_bytebuffer.h @@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_JNI_BYTEBUFFER_H_ +#define BASE_ANDROID_JNI_BYTEBUFFER_H_ + +#include + +#include "base/base_export.h" +#include "base/containers/span.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace base::android { + +// Given a JNIEnv and a jobject representing a byte buffer, produce a base::span +// corresponding to that byte buffer. These crash at runtime if the passed-in +// jobject does not correspond to a java.nio.Buffer, or if the passed-in buffer +// is unaligned and the current CPU architecture may sometimes require aligned +// accesses - this requirement is enforced even if your code never actually +// *does* the types of accesses that require alignment. +// +// Usually, that is what you want, since both of those conditions are programmer +// errors. +// +// If needed, there are also variants below starting with Maybe that return +// absl::nullopt in that case and do not crash. +base::span BASE_EXPORT JavaByteBufferToSpan(JNIEnv* env, + jobject buffer); + +base::span BASE_EXPORT JavaByteBufferToMutableSpan(JNIEnv* env, + jobject buffer); + +absl::optional> BASE_EXPORT +MaybeJavaByteBufferToSpan(JNIEnv* env, jobject buffer); + +absl::optional> BASE_EXPORT +MaybeJavaByteBufferToMutableSpan(JNIEnv* env, jobject buffer); + +} // namespace base::android + +#endif // BASE_ANDROID_JNI_BYTEBUFFER_H_ diff --git a/naiveproxy/src/base/android/jni_conversions.cc b/naiveproxy/src/base/android/jni_conversions.cc new file mode 100644 index 0000000000..6d7849cba8 --- /dev/null +++ b/naiveproxy/src/base/android/jni_conversions.cc @@ -0,0 +1,27 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include +#include + +#include "base/android/jni_string.h" +#include "base/base_export.h" +#include "third_party/jni_zero/jni_zero.h" + +namespace jni_zero { + +template <> +BASE_EXPORT std::string ConvertType( + JNIEnv* env, + const JavaRef& input) { + return base::android::ConvertJavaStringToUTF8(env, input); +} + +template <> +BASE_EXPORT std::u16string ConvertType( + JNIEnv* env, + const JavaRef& input) { + return base::android::ConvertJavaStringToUTF16(env, input); +} + +} // namespace jni_zero diff --git a/naiveproxy/src/base/android/jni_string.cc b/naiveproxy/src/base/android/jni_string.cc index 9720e2ca73..ed0fa806c3 100644 --- a/naiveproxy/src/base/android/jni_string.cc +++ b/naiveproxy/src/base/android/jni_string.cc @@ -9,6 +9,9 @@ #include "base/numerics/safe_conversions.h" #include "base/strings/utf_string_conversions.h" +// Size of buffer to allocate on the stack for string conversion. +#define BUFFER_SIZE 1024 + namespace { // Internal version that does not use a scoped local pointer. @@ -38,14 +41,29 @@ void ConvertJavaStringToUTF8(JNIEnv* env, jstring str, std::string* result) { CheckException(env); return; } - // JNI's GetStringUTFChars() returns strings in Java "modified" UTF8, so - // instead get the String in UTF16 and convert using chromium's conversion - // function that yields plain (non Java-modified) UTF8. - const jchar* chars = env->GetStringChars(str, NULL); - DCHECK(chars); - UTF16ToUTF8(reinterpret_cast(chars), - static_cast(length), result); - env->ReleaseStringChars(str, chars); + // JNI's GetStringUTFChars() and GetStringUTFRegion returns strings in Java + // "modified" UTF8, so instead get the String in UTF16 and convert using + // chromium's conversion function that yields plain (non Java-modified) UTF8. + if (length <= BUFFER_SIZE) { + // fast path, allocate temporary buffer on the stack and use GetStringRegion + // to copy the utf-16 characters into it with no heap allocation. + // https://developer.android.com/training/articles/perf-jni#utf-8-and-utf-16-strings:~:text=stack%2Dallocated%20buffer + std::array chars; + // GetStringRegion does not copy a null terminated string so the length must + // be explicitly passed to UTF16ToUTF8. + env->GetStringRegion(str, 0, length, chars.data()); + UTF16ToUTF8(reinterpret_cast(chars.data()), + static_cast(length), result); + } else { + // slow path + // GetStringChars doesn't NULL-terminate the strings it returns, so the + // length must be explicitly passed to UTF16ToUTF8. + const jchar* chars = env->GetStringChars(str, NULL); + DCHECK(chars); + UTF16ToUTF8(reinterpret_cast(chars), + static_cast(length), result); + env->ReleaseStringChars(str, chars); + } CheckException(env); } @@ -91,13 +109,26 @@ void ConvertJavaStringToUTF16(JNIEnv* env, CheckException(env); return; } - const jchar* chars = env->GetStringChars(str, NULL); - DCHECK(chars); - // GetStringChars isn't required to NULL-terminate the strings - // it returns, so the length must be explicitly checked. - result->assign(reinterpret_cast(chars), - static_cast(length)); - env->ReleaseStringChars(str, chars); + if (length <= BUFFER_SIZE) { + // fast path, allocate temporary buffer on the stack and use GetStringRegion + // to copy the utf-16 characters into it with no heap allocation. + // https://developer.android.com/training/articles/perf-jni#utf-8-and-utf-16-strings:~:text=stack%2Dallocated%20buffer + std::array chars; + env->GetStringRegion(str, 0, length, chars.data()); + // GetStringRegion does not copy a null terminated string so the length must + // be explicitly passed to assign. + result->assign(reinterpret_cast(chars.data()), + static_cast(length)); + } else { + // slow path + const jchar* chars = env->GetStringChars(str, NULL); + DCHECK(chars); + // GetStringChars doesn't NULL-terminate the strings it returns, so the + // length must be explicitly passed to assign. + result->assign(reinterpret_cast(chars), + static_cast(length)); + env->ReleaseStringChars(str, chars); + } CheckException(env); } diff --git a/naiveproxy/src/base/android/linker/BUILD.gn b/naiveproxy/src/base/android/linker/BUILD.gn index e7b6870fbb..662c56cf27 100644 --- a/naiveproxy/src/base/android/linker/BUILD.gn +++ b/naiveproxy/src/base/android/linker/BUILD.gn @@ -17,7 +17,7 @@ shared_library("chromium_android_linker") { deps = [ "//build:buildflag_header_h", - "//third_party/jni_zero:jni_export", + "//third_party/jni_zero:jni_zero", ] # Export JNI symbols. diff --git a/naiveproxy/src/base/android/linker/linker_jni.h b/naiveproxy/src/base/android/linker/linker_jni.h index 4f8b681aa4..a38382c10d 100644 --- a/naiveproxy/src/base/android/linker/linker_jni.h +++ b/naiveproxy/src/base/android/linker/linker_jni.h @@ -22,7 +22,7 @@ #include #include "build/build_config.h" -#include "third_party/jni_zero/jni_export.h" +#include "third_party/jni_zero/jni_zero.h" // Set this to 1 to enable debug traces to the Android log. // Note that LOG() from "base/logging.h" cannot be used, since it is diff --git a/naiveproxy/src/base/android/memory_pressure_listener_android.cc b/naiveproxy/src/base/android/memory_pressure_listener_android.cc index 1779263aea..c1e9cf5c5f 100644 --- a/naiveproxy/src/base/android/memory_pressure_listener_android.cc +++ b/naiveproxy/src/base/android/memory_pressure_listener_android.cc @@ -20,7 +20,7 @@ static void JNI_MemoryPressureListener_OnMemoryPressure( } static void JNI_MemoryPressureListener_OnPreFreeze(JNIEnv* env) { - base::PreFreezeBackgroundMemoryTrimmer::OnPreFreeze(); + base::android::PreFreezeBackgroundMemoryTrimmer::OnPreFreeze(); } namespace base::android { diff --git a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc index 5e7bff30fc..0705e742a9 100644 --- a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc +++ b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.cc @@ -3,21 +3,104 @@ // found in the LICENSE file. #include "base/android/pre_freeze_background_memory_trimmer.h" -#include "base/android/build_info.h" -#include "base/feature_list.h" -#include "base/logging.h" -#include "base/task/sequenced_task_runner.h" -namespace base { +#include "base/android/build_info.h" +#include "base/android/pmf_utils.h" +#include "base/check.h" +#include "base/command_line.h" +#include "base/feature_list.h" +#include "base/functional/bind.h" +#include "base/logging.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" +#include "base/task/thread_pool/thread_pool_instance.h" +#include "base/time/time.h" + +#include +#include + +namespace base::android { +namespace { + +// This constant is chosen arbitrarily, to allow time for the background tasks +// to finish running BEFORE collecting metrics. +const base::TimeDelta kDelayForMetrics = base::Seconds(2); + +std::optional GetPrivateMemoryFootprint() { + return PmfUtils::GetPrivateMemoryFootprintForCurrentProcess(); +} + +uint64_t BytesToMiB(uint64_t v) { + return v / 1024 / 1024; +} + +const char* GetProcessType() { + CHECK(base::CommandLine::InitializedForCurrentProcess()); + const std::string type = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII("type"); + const char* process_type = type == "" ? "Browser" + : type == "renderer" ? "Renderer" + : type == "gpu-process" ? "Gpu" + : type == "utility" ? "Utility" + : "Unknown"; + return process_type; +} + +std::string GetMetricName(const char* suffix) { + CHECK(base::CommandLine::InitializedForCurrentProcess()); + const char* process_type = GetProcessType(); + return StrCat( + {"Memory.PreFreeze2.", process_type, ".PrivateMemoryFootprint.", suffix}); +} + +void MaybeRecordMetric(const std::string metric_name, + std::optional value_bytes) { + // Skip recording the metric if we failed to get the PMF. + if (!value_bytes.has_value()) { + return; + } + UmaHistogramMemoryMB(metric_name, + static_cast(BytesToMiB(value_bytes.value()))); +} + +std::optional PmfDiff(std::optional pmf_before, + std::optional pmf_after) { + if (!pmf_before.has_value() || !pmf_before.has_value()) { + return std::nullopt; + } + + const uint64_t pmf_before_value = pmf_before.value(); + const uint64_t pmf_after_value = pmf_after.value(); + + return pmf_after_value < pmf_before_value ? pmf_before_value - pmf_after_value + : 0; +} + +void RecordMetrics(std::optional pmf_before) { + CHECK(base::CommandLine::InitializedForCurrentProcess()); + + std::string before_name = GetMetricName("Before"); + std::string after_name = GetMetricName("After"); + std::string diff_name = GetMetricName("Diff"); + + std::optional pmf_after = GetPrivateMemoryFootprint(); + + MaybeRecordMetric(before_name, pmf_before); + MaybeRecordMetric(after_name, pmf_after); + MaybeRecordMetric(diff_name, PmfDiff(pmf_before, pmf_after)); +} + +} // namespace BASE_FEATURE(kOnPreFreezeMemoryTrim, "OnPreFreezeMemoryTrim", FEATURE_DISABLED_BY_DEFAULT); PreFreezeBackgroundMemoryTrimmer::PreFreezeBackgroundMemoryTrimmer() - : is_respecting_modern_trim_( - base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_U) {} + : is_respecting_modern_trim_(BuildInfo::GetInstance()->sdk_int() >= + SDK_VERSION_U) {} // static PreFreezeBackgroundMemoryTrimmer& PreFreezeBackgroundMemoryTrimmer::Instance() { @@ -25,6 +108,34 @@ PreFreezeBackgroundMemoryTrimmer& PreFreezeBackgroundMemoryTrimmer::Instance() { return *instance; } +void PreFreezeBackgroundMemoryTrimmer::PostMetricsTask( + std::optional pmf_before) { + // PreFreeze is only for Android U and greater, so no need to record metrics + // for older versions. + if (!IsRespectingModernTrim()) { + return; + } + + // We need the process type to record the metrics below, which we get from + // the command line. We cannot post the task below if the thread pool is not + // initialized yet. + if (!base::CommandLine::InitializedForCurrentProcess() || + !base::ThreadPoolInstance::Get()) { + return; + } + + // The posted task will be more likely to survive background killing in + // experiments that change the memory trimming behavior. Run as USER_BLOCKING + // to reduce this sample imbalance in experiment groups. Normally tasks + // collecting metrics should use BEST_EFFORT, but when running in background a + // number of subtle effects may influence the real delay of those tasks. The + // USER_BLOCKING will allow to estimate the number of better-survived tasks + // more precisely. + base::ThreadPool::PostDelayedTask( + FROM_HERE, {base::TaskPriority::USER_BLOCKING, MayBlock()}, + base::BindOnce(&RecordMetrics, pmf_before), kDelayForMetrics); +} + // static void PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTask( scoped_refptr task_runner, @@ -40,8 +151,16 @@ void PreFreezeBackgroundMemoryTrimmer::PostDelayedBackgroundTaskInternal( const base::Location& from_here, base::OnceClosure task, base::TimeDelta delay) { - if (!IsRespectingModernTrim() || - !base::FeatureList::IsEnabled(kOnPreFreezeMemoryTrim)) { + // Preserve previous behaviour on versions before Android U. + if (!IsRespectingModernTrim()) { + task_runner->PostDelayedTask(from_here, std::move(task), delay); + } + + { + base::AutoLock locker(lock_); + did_register_task_ = true; + } + if (!base::FeatureList::IsEnabled(kOnPreFreezeMemoryTrim)) { task_runner->PostDelayedTask(from_here, std::move(task), delay); return; } @@ -81,12 +200,16 @@ void PreFreezeBackgroundMemoryTrimmer::OnPreFreeze() { } void PreFreezeBackgroundMemoryTrimmer::OnPreFreezeInternal() { + base::AutoLock locker(lock_); + if (did_register_task_) { + PostMetricsTask(GetPrivateMemoryFootprint()); + } + if (!IsRespectingModernTrim() || !base::FeatureList::IsEnabled(kOnPreFreezeMemoryTrim)) { return; } - base::AutoLock locker(lock_); while (!background_tasks_.empty()) { auto background_task = std::move(background_tasks_.front()); background_tasks_.pop_front(); @@ -186,4 +309,4 @@ void PreFreezeBackgroundMemoryTrimmer::BackgroundTask::Start( delay); } -} // namespace base +} // namespace base::android diff --git a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.h b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.h index dc81e043ac..22708cb163 100644 --- a/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.h +++ b/naiveproxy/src/base/android/pre_freeze_background_memory_trimmer.h @@ -14,7 +14,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/timer/timer.h" -namespace base { +namespace base::android { BASE_EXPORT BASE_DECLARE_FEATURE(kOnPreFreezeMemoryTrim); @@ -40,16 +40,16 @@ class BASE_EXPORT PreFreezeBackgroundMemoryTrimmer { scoped_refptr task_runner, const base::Location& from_here, base::OnceClosure task, - base::TimeDelta delay); + base::TimeDelta delay) LOCKS_EXCLUDED(lock_); static void SetIsRespectingModernTrimForTesting(bool is_respecting); - size_t GetNumberOfPendingBackgroundTasksForTesting(); + size_t GetNumberOfPendingBackgroundTasksForTesting() LOCKS_EXCLUDED(lock_); - static void OnPreFreezeForTesting() { OnPreFreeze(); } + static void OnPreFreezeForTesting() LOCKS_EXCLUDED(lock_) { OnPreFreeze(); } // Called when Chrome is about to be frozen. Runs as many delayed tasks as // possible immediately, before we are frozen. - static void OnPreFreeze(); + static void OnPreFreeze() LOCKS_EXCLUDED(lock_); private: friend class base::NoDestructor; @@ -84,7 +84,7 @@ class BASE_EXPORT PreFreezeBackgroundMemoryTrimmer { PreFreezeBackgroundMemoryTrimmer(); - static void UnregisterBackgroundTask(BackgroundTask*); + static void UnregisterBackgroundTask(BackgroundTask*) LOCKS_EXCLUDED(lock_); void UnregisterBackgroundTaskInternal(BackgroundTask*) LOCKS_EXCLUDED(lock_); @@ -94,20 +94,25 @@ class BASE_EXPORT PreFreezeBackgroundMemoryTrimmer { scoped_refptr task_runner, const base::Location& from_here, base::OnceClosure task, - base::TimeDelta delay); + base::TimeDelta delay) LOCKS_EXCLUDED(lock_); void PostDelayedBackgroundTaskModern( scoped_refptr task_runner, const base::Location& from_here, base::OnceClosure task, - base::TimeDelta delay); + base::TimeDelta delay) LOCKS_EXCLUDED(lock_); - void OnPreFreezeInternal(); + void OnPreFreezeInternal() LOCKS_EXCLUDED(lock_); + + void PostMetricsTask(std::optional pmf_before); mutable base::Lock lock_; std::deque> background_tasks_ GUARDED_BY(lock_); + // Keeps track of whether any tasks have been registered so far (set to true + // once the first task is registered). + bool did_register_task_ GUARDED_BY(lock_) = false; bool is_respecting_modern_trim_; }; -} // namespace base +} // namespace base::android #endif // BASE_ANDROID_PRE_FREEZE_BACKGROUND_MEMORY_TRIMMER_H_ diff --git a/naiveproxy/src/base/android/proguard/chromium_code.flags b/naiveproxy/src/base/android/proguard/chromium_code.flags index 6393108051..e417fbaaa5 100644 --- a/naiveproxy/src/base/android/proguard/chromium_code.flags +++ b/naiveproxy/src/base/android/proguard/chromium_code.flags @@ -43,6 +43,11 @@ (); } +# Required to remove fields until b/274802355 is resolved. +-assumevalues class !cr_allowunused,** { + final org.chromium.base.ThreadUtils$ThreadChecker * return _NONNULL_; +} + # TODO(agrieve): Remove once we start to use Android U SDK. -dontwarn android.window.BackEvent -dontwarn android.window.OnBackAnimationCallback diff --git a/naiveproxy/src/base/android/robolectric_jni_onload.cc b/naiveproxy/src/base/android/robolectric_jni_onload.cc new file mode 100644 index 0000000000..ba537e6316 --- /dev/null +++ b/naiveproxy/src/base/android/robolectric_jni_onload.cc @@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include + +#include "base/android/base_jni_onload.h" +#include "base/android/jni_android.h" + +extern "C" JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + base::android::OnJNIOnLoadInit(); + return JNI_VERSION_1_4; +} diff --git a/naiveproxy/src/base/android/scoped_java_ref.h b/naiveproxy/src/base/android/scoped_java_ref.h index ddac907807..2e5cf817a6 100644 --- a/naiveproxy/src/base/android/scoped_java_ref.h +++ b/naiveproxy/src/base/android/scoped_java_ref.h @@ -5,7 +5,7 @@ #ifndef BASE_ANDROID_SCOPED_JAVA_REF_H_ #define BASE_ANDROID_SCOPED_JAVA_REF_H_ -#include "third_party/jni_zero/scoped_java_ref.h" +#include "third_party/jni_zero/jni_zero.h" namespace base { namespace android { diff --git a/naiveproxy/src/base/android/task_scheduler/post_task_android.cc b/naiveproxy/src/base/android/task_scheduler/post_task_android.cc index c47be55257..fbf9ff2577 100644 --- a/naiveproxy/src/base/android/task_scheduler/post_task_android.cc +++ b/naiveproxy/src/base/android/task_scheduler/post_task_android.cc @@ -10,7 +10,7 @@ namespace base { // static void PostTaskAndroid::SignalNativeSchedulerReady() { - Java_PostTask_onNativeSchedulerReady(base::android::AttachCurrentThread()); + Java_PostTask_onNativeSchedulerReady(jni_zero::AttachCurrentThread()); } } // namespace base diff --git a/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc b/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc index e8fb2ca8b1..66fae635a4 100644 --- a/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc +++ b/naiveproxy/src/base/android/task_scheduler/task_runner_android.cc @@ -41,7 +41,7 @@ void RunJavaTask(base::android::ScopedJavaGlobalRef task, base::StrCat({"JniPostTask: ", runnable_class_name}); ctx.event()->set_name(event_name.c_str()); }); - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); JNI_Runnable::Java_Runnable_run(env, task); } diff --git a/naiveproxy/src/base/android/token_android.cc b/naiveproxy/src/base/android/token_android.cc new file mode 100644 index 0000000000..34bec993b0 --- /dev/null +++ b/naiveproxy/src/base/android/token_android.cc @@ -0,0 +1,30 @@ +// Copyright 2024 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/android/token_android.h" + +#include "base/base_jni/Token_jni.h" + +namespace base { +namespace android { + +ScopedJavaLocalRef TokenAndroid::Create(JNIEnv* env, + const base::Token& token) { + return Java_Token_Constructor(env, static_cast(token.high()), + static_cast(token.low())); +} + +base::Token TokenAndroid::FromJavaToken(JNIEnv* env, + const JavaRef& j_token) { + const uint64_t high = static_cast(Java_Token_getHigh(env, j_token)); + const uint64_t low = static_cast(Java_Token_getLow(env, j_token)); + return base::Token(high, low); +} + +static ScopedJavaLocalRef JNI_Token_CreateRandom(JNIEnv* env) { + return TokenAndroid::Create(env, base::Token::CreateRandom()); +} + +} // namespace android +} // namespace base diff --git a/naiveproxy/src/base/android/token_android.h b/naiveproxy/src/base/android/token_android.h new file mode 100644 index 0000000000..d1140fe464 --- /dev/null +++ b/naiveproxy/src/base/android/token_android.h @@ -0,0 +1,35 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_ANDROID_TOKEN_ANDROID_H_ +#define BASE_ANDROID_TOKEN_ANDROID_H_ + +#include + +#include "base/android/scoped_java_ref.h" +#include "base/base_export.h" +#include "base/token.h" + +namespace base { +namespace android { + +class BASE_EXPORT TokenAndroid { + public: + // Create a Java Token with the same value as `token`. + static ScopedJavaLocalRef Create(JNIEnv* env, + const base::Token& token); + + // Creates a Token from `j_token`. + static base::Token FromJavaToken(JNIEnv* env, + const JavaRef& j_token); + + TokenAndroid() = delete; + TokenAndroid(const TokenAndroid&) = delete; + TokenAndroid& operator=(const TokenAndroid&) = delete; +}; + +} // namespace android +} // namespace base + +#endif // BASE_ANDROID_TOKEN_ANDROID_H_ diff --git a/naiveproxy/src/base/android/trace_event_binding.cc b/naiveproxy/src/base/android/trace_event_binding.cc index 5da0df0989..0739cccecd 100644 --- a/naiveproxy/src/base/android/trace_event_binding.cc +++ b/naiveproxy/src/base/android/trace_event_binding.cc @@ -47,7 +47,7 @@ class TraceEnabledObserver : public perfetto::TrackEventSessionObserver { } void OnStart(const perfetto::DataSourceBase::StartArgs&) override { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::Java_TraceEvent_setEnabled(env, true); base::android::Java_TraceEvent_setEventNameFilteringEnabled( env, EventNameFilteringEnabled()); @@ -56,7 +56,7 @@ class TraceEnabledObserver : public perfetto::TrackEventSessionObserver { void OnStop(const perfetto::DataSourceBase::StopArgs& args) override { event_name_filtering_per_session_.erase(args.internal_instance_index); - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::Java_TraceEvent_setEnabled( env, !event_name_filtering_per_session_.empty()); base::android::Java_TraceEvent_setEventNameFilteringEnabled( @@ -92,7 +92,7 @@ class TraceEnabledObserver // trace_event::TraceLog::EnabledStateObserver: void OnTraceLogEnabled() override { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::Java_TraceEvent_setEnabled(env, true); if (base::trace_event::TraceLog::GetInstance() ->GetCurrentTraceConfig() @@ -102,7 +102,7 @@ class TraceEnabledObserver } void OnTraceLogDisabled() override { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); base::android::Java_TraceEvent_setEnabled(env, false); base::android::Java_TraceEvent_setEventNameFilteringEnabled(env, false); } diff --git a/naiveproxy/src/base/base64.cc b/naiveproxy/src/base/base64.cc index e7afd31800..c333fd95a6 100644 --- a/naiveproxy/src/base/base64.cc +++ b/naiveproxy/src/base/base64.cc @@ -46,10 +46,6 @@ void Base64EncodeAppend(span input, std::string* output) { CHECK_EQ(output->size(), prefix_len + output_size); } -void Base64Encode(StringPiece input, std::string* output) { - *output = Base64Encode(base::as_byte_span(input)); -} - std::string Base64Encode(StringPiece input) { return Base64Encode(base::as_byte_span(input)); } diff --git a/naiveproxy/src/base/base64.h b/naiveproxy/src/base/base64.h index 65d52e6bab..6c35e66571 100644 --- a/naiveproxy/src/base/base64.h +++ b/naiveproxy/src/base/base64.h @@ -24,11 +24,6 @@ BASE_EXPORT std::string Base64Encode(span input); BASE_EXPORT void Base64EncodeAppend(span input, std::string* output); -// Encodes the input string in base64. -// DEPRECATED, use `std::string Base64Encode(StringPiece input)` instead. -// TODO(crbug.com/1486214): Remove this. -BASE_EXPORT void Base64Encode(StringPiece input, std::string* output); - // Encodes the input string in base64. BASE_EXPORT std::string Base64Encode(StringPiece input); diff --git a/naiveproxy/src/base/base_paths_android.cc b/naiveproxy/src/base/base_paths_android.cc index 79e9318faa..482b5baf0c 100644 --- a/naiveproxy/src/base/base_paths_android.cc +++ b/naiveproxy/src/base/base_paths_android.cc @@ -16,7 +16,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/process/process_metrics.h" namespace base { diff --git a/naiveproxy/src/base/base_paths_apple.cc b/naiveproxy/src/base/base_paths_apple.cc index 62e3caaa15..d5f127f722 100644 --- a/naiveproxy/src/base/base_paths_apple.cc +++ b/naiveproxy/src/base/base_paths_apple.cc @@ -11,7 +11,6 @@ #include "base/check_op.h" #include "base/files/file_path.h" #include "base/files/file_util.h" -#include "base/strings/string_util.h" #include "base/threading/thread_restrictions.h" namespace base::apple::internal { @@ -22,9 +21,12 @@ base::FilePath GetExecutablePath() { uint32_t executable_length = 0; _NSGetExecutablePath(NULL, &executable_length); DCHECK_GT(executable_length, 1u); - std::string executable_path; - int rv = _NSGetExecutablePath( - base::WriteInto(&executable_path, executable_length), &executable_length); + // `executable_length` is the total buffer size required including the NUL + // terminator, while `basic_string` guarantees that enough space is reserved + // so that index may be any value between 0 and size() inclusive, though it is + // UB to set `str[size()]` to anything other than '\0'. + std::string executable_path(executable_length - 1, '\0'); + int rv = _NSGetExecutablePath(executable_path.data(), &executable_length); DCHECK_EQ(rv, 0); // _NSGetExecutablePath may return paths containing ./ or ../ which makes diff --git a/naiveproxy/src/base/base_paths_fuchsia.cc b/naiveproxy/src/base/base_paths_fuchsia.cc index 0a74d53790..1d290d2bb6 100644 --- a/naiveproxy/src/base/base_paths_fuchsia.cc +++ b/naiveproxy/src/base/base_paths_fuchsia.cc @@ -9,7 +9,7 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/fuchsia/file_utils.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/path_service.h" #include "base/process/process.h" diff --git a/naiveproxy/src/base/base_switches.cc b/naiveproxy/src/base/base_switches.cc index 67f34db667..caf961ccf2 100644 --- a/naiveproxy/src/base/base_switches.cc +++ b/naiveproxy/src/base/base_switches.cc @@ -65,6 +65,10 @@ const char kFullMemoryCrashReport[] = "full-memory-crash-report"; // to BEST_EFFORT are not logged. const char kLogBestEffortTasks[] = "log-best-effort-tasks"; +// Handle to the shared memory segment a child process should use to transmit +// histograms back to the browser process. +const char kMetricsSharedMemoryHandle[] = "metrics-shmem-handle"; + // Suppresses all error dialogs when present. const char kNoErrorDialogs[] = "noerrdialogs"; @@ -172,13 +176,6 @@ const char kPackageVersionName[] = "package-version-name"; const char kPackageVersionCode[] = "package-version-code"; #endif -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -// TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when -// Crashpad is fully enabled on Linux. Indicates that Crashpad should be -// enabled. -extern const char kEnableCrashpad[] = "enable-crashpad"; -#endif - #if BUILDFLAG(IS_CHROMEOS) // Override the default scheduling boosting value for urgent tasks. // This can be adjusted if a specific chromeos device shows better perf/power diff --git a/naiveproxy/src/base/base_switches.h b/naiveproxy/src/base/base_switches.h index b30c29e4e0..8e617b5960 100644 --- a/naiveproxy/src/base/base_switches.h +++ b/naiveproxy/src/base/base_switches.h @@ -24,6 +24,7 @@ extern const char kFieldTrialHandle[]; extern const char kForceFieldTrials[]; extern const char kFullMemoryCrashReport[]; extern const char kLogBestEffortTasks[]; +extern const char kMetricsSharedMemoryHandle[]; extern const char kNoErrorDialogs[]; extern const char kProfilingAtStart[]; extern const char kProfilingFile[]; @@ -60,12 +61,6 @@ extern const char kPackageVersionName[]; extern const char kPackageVersionCode[]; #endif -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -// TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when -// Crashpad is fully enabled on Linux. -extern const char kEnableCrashpad[]; -#endif - #if BUILDFLAG(IS_CHROMEOS) extern const char kSchedulerBoostUrgent[]; #endif diff --git a/naiveproxy/src/base/big_endian.cc b/naiveproxy/src/base/big_endian.cc index fe5ff2c959..fa6e4d6a29 100644 --- a/naiveproxy/src/base/big_endian.cc +++ b/naiveproxy/src/base/big_endian.cc @@ -6,6 +6,7 @@ #include +#include "base/numerics/byte_conversions.h" #include "base/numerics/checked_math.h" #include "base/strings/string_piece.h" @@ -17,137 +18,167 @@ BigEndianReader BigEndianReader::FromStringPiece( } BigEndianReader::BigEndianReader(const uint8_t* buf, size_t len) - : ptr_(buf), end_(ptr_ + len) { - // Ensure `len` does not cause `end_` to wrap around. - CHECK_GE(end_, ptr_); -} + : // TODO(crbug.com/40284755): Remove this constructor entirely, callers + // should use span constructor. + UNSAFE_BUFFERS(buffer_(buf, len)) {} -BigEndianReader::BigEndianReader(base::span buf) - : ptr_(buf.data()), end_(buf.data() + buf.size()) {} +BigEndianReader::BigEndianReader(base::span buffer) + : buffer_(buffer) {} + +BigEndianReader::~BigEndianReader() = default; bool BigEndianReader::Skip(size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; - ptr_ += len; + } + buffer_ = buffer_.subspan(len); return true; } bool BigEndianReader::ReadBytes(void* out, size_t len) { - if (len > remaining()) - return false; - memcpy(out, ptr_, len); - ptr_ += len; - return true; + std::optional> o = ReadSpan(len); + if (o.has_value()) { + memcpy(out, o->data(), o->size_bytes()); + return true; + } + return false; } bool BigEndianReader::ReadPiece(base::StringPiece* out, size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; - *out = base::StringPiece(reinterpret_cast(ptr_), len); - ptr_ += len; + } + auto [view, remain] = buffer_.split_at(len); + *out = base::StringPiece(reinterpret_cast(view.data()), + view.size()); + buffer_ = remain; return true; } -bool BigEndianReader::ReadSpan(base::span* out, size_t len) { - if (len > remaining()) - return false; - *out = base::make_span(ptr_, len); - ptr_ += len; - return true; -} - -template -bool BigEndianReader::Read(T* value) { - if (sizeof(T) > remaining()) - return false; - ReadBigEndian(ptr_, value); - ptr_ += sizeof(T); - return true; +std::optional> BigEndianReader::ReadSpan( + base::StrictNumeric n) { + if (remaining() < size_t{n}) { + return std::nullopt; + } + auto [consume, remain] = buffer_.split_at(n); + buffer_ = remain; + return {consume}; } bool BigEndianReader::ReadU8(uint8_t* value) { - return Read(value); -} - -bool BigEndianReader::ReadU16(uint16_t* value) { - return Read(value); -} - -bool BigEndianReader::ReadU32(uint32_t* value) { - return Read(value); -} - -bool BigEndianReader::ReadU64(uint64_t* value) { - return Read(value); -} - -template -bool BigEndianReader::ReadLengthPrefixed(base::StringPiece* out) { - T t_len; - if (!Read(&t_len)) - return false; - size_t len = strict_cast(t_len); - const uint8_t* original_ptr = ptr_; - if (!Skip(len)) { - ptr_ -= sizeof(T); + std::optional> bytes = ReadFixedSpan<1u>(); + if (!bytes.has_value()) { return false; } - *out = base::StringPiece(reinterpret_cast(original_ptr), len); + *value = numerics::U8FromBigEndian(*bytes); return true; } -bool BigEndianReader::ReadU8LengthPrefixed(base::StringPiece* out) { - return ReadLengthPrefixed(out); +bool BigEndianReader::ReadU16(uint16_t* value) { + std::optional> bytes = ReadFixedSpan<2u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U16FromBigEndian(*bytes); + return true; } -bool BigEndianReader::ReadU16LengthPrefixed(base::StringPiece* out) { - return ReadLengthPrefixed(out); +bool BigEndianReader::ReadU32(uint32_t* value) { + std::optional> bytes = ReadFixedSpan<4u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U32FromBigEndian(*bytes); + return true; } +bool BigEndianReader::ReadU64(uint64_t* value) { + std::optional> bytes = ReadFixedSpan<8u>(); + if (!bytes.has_value()) { + return false; + } + *value = numerics::U64FromBigEndian(*bytes); + return true; +} + +bool BigEndianReader::ReadU8LengthPrefixed(std::string_view* out) { + span rollback = buffer_; + uint8_t len; + if (!ReadU8(&len)) { + return false; + } + const bool ok = ReadPiece(out, len); + if (!ok) { + buffer_ = rollback; // Undo the ReadU8. + } + return ok; +} + +bool BigEndianReader::ReadU16LengthPrefixed(std::string_view* out) { + span rollback = buffer_; + uint16_t len; + if (!ReadU16(&len)) { + return false; + } + const bool ok = ReadPiece(out, len); + if (!ok) { + buffer_ = rollback; // Undo the ReadU8. + } + return ok; +} + +BigEndianWriter::BigEndianWriter(span buffer) : buffer_(buffer) {} + BigEndianWriter::BigEndianWriter(char* buf, size_t len) - : ptr_(buf), end_(ptr_ + len) { - // Ensure `len` does not cause `end_` to wrap around. - CHECK_GE(end_, ptr_); -} + : // TODO(crbug.com/40284755): Remove this constructor entirely, callers + // should use span constructor. + UNSAFE_BUFFERS(buffer_(reinterpret_cast(buf), len)) {} + +BigEndianWriter::~BigEndianWriter() = default; bool BigEndianWriter::Skip(size_t len) { - if (len > remaining()) + if (len > remaining()) { return false; - ptr_ += len; + } + buffer_ = buffer_.subspan(len); return true; } bool BigEndianWriter::WriteBytes(const void* buf, size_t len) { - if (len > remaining()) - return false; - memcpy(ptr_, buf, len); - ptr_ += len; - return true; + return WriteSpan( + // TODO(crbug.com/40284755): Remove WriteBytes() entirely, callers + // should use WriteSpan().. + UNSAFE_BUFFERS((base::span(static_cast(buf), len)))); } -template -bool BigEndianWriter::Write(T value) { - if (sizeof(T) > remaining()) +bool BigEndianWriter::WriteSpan(base::span bytes) { + if (remaining() < bytes.size()) { return false; - WriteBigEndian(ptr_, value); - ptr_ += sizeof(T); + } + auto [write, remain] = buffer_.split_at(bytes.size()); + write.copy_from(bytes); + buffer_ = remain; return true; } bool BigEndianWriter::WriteU8(uint8_t value) { - return Write(value); + // TODO(danakj) this span constructor should be implicit. + return WriteFixedSpan(base::span(numerics::U8ToBigEndian(value))); } bool BigEndianWriter::WriteU16(uint16_t value) { - return Write(value); + // TODO(danakj) this span constructor should be implicit. + return WriteFixedSpan(base::span(numerics::U16ToBigEndian(value))); } bool BigEndianWriter::WriteU32(uint32_t value) { - return Write(value); + // TODO(danakj) this span constructor should be implicit. + return WriteFixedSpan(base::span(numerics::U32ToBigEndian(value))); } bool BigEndianWriter::WriteU64(uint64_t value) { - return Write(value); + // TODO(danakj) this span constructor should be implicit. + return WriteFixedSpan(base::span(numerics::U64ToBigEndian(value))); } } // namespace base diff --git a/naiveproxy/src/base/big_endian.h b/naiveproxy/src/base/big_endian.h index 37e7947384..4a89ca44d8 100644 --- a/naiveproxy/src/base/big_endian.h +++ b/naiveproxy/src/base/big_endian.h @@ -8,11 +8,13 @@ #include #include #include +#include #include #include "base/base_export.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" -#include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" #include "base/strings/string_piece.h" #include "base/sys_byteorder.h" #include "build/build_config.h" @@ -57,25 +59,44 @@ inline uint8_t ByteSwapIfLittleEndian(uint8_t val) { // NOTE(szym): glibc dns-canon.c use ntohs(*(uint16_t*)ptr) which is // potentially unaligned. // This would cause SIGBUS on ARMv5 or earlier and ARMv6-M. +// +// DEPRECATED: Use base::numerics::*FromBigEndian to convert big-endian byte +// encoding to primitives. template -inline void ReadBigEndian(const uint8_t buf[], T* out) { +inline void ReadBigEndian(span buffer, T* out) { static_assert(std::is_integral_v, "T has to be an integral type."); // Make an unsigned version of the output type to make shift possible // without UB. - typename std::make_unsigned::type raw; - memcpy(&raw, buf, sizeof(T)); + std::make_unsigned_t raw; + byte_span_from_ref(raw).copy_from(buffer); *out = static_cast(internal::ByteSwapIfLittleEndian(raw)); } -// Write an integer (signed or unsigned) |val| to |buf| in Big Endian order. -// Note: this loop is unrolled with -O1 and above. -template -inline void WriteBigEndian(char buf[], T val) { - static_assert(std::is_integral_v, "T has to be an integral type."); - const auto unsigned_val = - static_cast::type>(val); +// TODO(crbug.com/40284755): Remove this function when there are no callers. +template +inline void ReadBigEndian(const uint8_t buf[], T* out) { + ReadBigEndian(span(buf, sizeof(T)), out); +} + +// Write an integer (signed or unsigned) `val` to `buffer` in Big Endian order. +// The `buffer` must be the same size (in bytes) as the integer `val`. +// +// DEPRECATED: Use base::numerics::*ToBigEndian to convert primitives to big- +// endian byte encoding. +template + requires(std::is_integral_v) +inline void WriteBigEndian(span buffer, T val) { + const auto unsigned_val = static_cast>(val); const auto raw = internal::ByteSwapIfLittleEndian(unsigned_val); - memcpy(buf, &raw, sizeof(T)); + buffer.copy_from(byte_span_from_ref(raw)); +} + +// TODO(crbug.com/40284755): Remove this function when there are no callers. +template + requires(std::is_integral_v) +inline void WriteBigEndian(char buf[], T val) { + return WriteBigEndian( + as_writable_bytes(span(buf, sizeof(T))), val); } // Allows reading integers in network order (big endian) while iterating over @@ -84,28 +105,43 @@ class BASE_EXPORT BigEndianReader { public: static BigEndianReader FromStringPiece(base::StringPiece string_piece); - explicit BigEndianReader(base::span buf); + explicit BigEndianReader(base::span buffer); - // TODO(crbug.com/1490484): Remove this overload. - BigEndianReader(const uint8_t* buf, size_t len); + // TODO(crbug.com/40284755): Remove this overload. + UNSAFE_BUFFER_USAGE BigEndianReader(const uint8_t* buf, size_t len); + + ~BigEndianReader(); // Returns a span over all unread bytes. - span remaining_bytes() const { - // SAFETY: The cast value is non-negative because `ptr_` is never moved past - // `end_`. - return make_span(ptr_, static_cast(end_ - ptr_)); - } + span remaining_bytes() const { return buffer_; } - // TODO(crbug.com/1490484): Remove this method. - const uint8_t* ptr() const { return ptr_; } - // TODO(crbug.com/1490484): Remove this method. - size_t remaining() const { return static_cast(end_ - ptr_); } + // TODO(crbug.com/40284755): Remove this method. + const uint8_t* ptr() const { return buffer_.data(); } + // TODO(crbug.com/40284755): Remove this method. + size_t remaining() const { return buffer_.size(); } bool Skip(size_t len); bool ReadBytes(void* out, size_t len); // Creates a StringPiece in |out| that points to the underlying buffer. bool ReadPiece(base::StringPiece* out, size_t len); - bool ReadSpan(base::span* out, size_t len); + + // Returns a span over `n` bytes from the buffer and moves the internal state + // past those bytes, or returns nullopt and if there are not `n` bytes + // remaining in the buffer. + std::optional> ReadSpan(base::StrictNumeric n); + + // Returns a span over `N` bytes from the buffer and moves the internal state + // past those bytes, or returns nullopt and if there are not `N` bytes + // remaining in the buffer. + template + std::optional> ReadFixedSpan() { + if (remaining() < N) { + return std::nullopt; + } + auto [consume, remain] = buffer_.split_at(); + buffer_ = remain; + return {consume}; + } bool ReadU8(uint8_t* value); bool ReadU16(uint16_t* value); @@ -127,39 +163,56 @@ class BASE_EXPORT BigEndianReader { bool ReadU16LengthPrefixed(base::StringPiece* out); private: - // Hidden to promote type safety. - template - bool Read(T* v); - template - bool ReadLengthPrefixed(base::StringPiece* out); - - const uint8_t* ptr_; - const uint8_t* end_; + // TODO(danakj): Switch to raw_span in its own CL. + span buffer_; }; // Allows writing integers in network order (big endian) while iterating over // an underlying buffer. All the writing functions advance the internal pointer. class BASE_EXPORT BigEndianWriter { public: - BigEndianWriter(char* buf, size_t len); + // Constructs a BigEndianWriter that will write into the given buffer. + BigEndianWriter(span buffer); - char* ptr() const { return ptr_; } - size_t remaining() const { return static_cast(end_ - ptr_); } + // TODO(crbug.com/40284755): Remove this overload. + UNSAFE_BUFFER_USAGE BigEndianWriter(char* buf, size_t len); + + ~BigEndianWriter(); + + char* ptr() const { return reinterpret_cast(buffer_.data()); } + size_t remaining() const { return buffer_.size(); } + + // Returns a span over all unwritten bytes. + span remaining_bytes() const { return buffer_; } bool Skip(size_t len); + // TODO(crbug.com/40284755): WriteBytes() calls should be replaced with + // WriteSpan(). bool WriteBytes(const void* buf, size_t len); bool WriteU8(uint8_t value); bool WriteU16(uint16_t value); bool WriteU32(uint32_t value); bool WriteU64(uint64_t value); - private: - // Hidden to promote type safety. - template - bool Write(T v); + // Writes the span of bytes to the backing buffer. If there is not enough + // room, it writes nothing and returns false. + bool WriteSpan(base::span bytes); - raw_ptr ptr_; - raw_ptr end_; + // Writes `N` bytes to the backing buffer. If there is not enough room, it + // writes nothing and returns false. + template + bool WriteFixedSpan(base::span bytes) { + if (remaining() < N) { + return false; + } + auto [write, remain] = buffer_.split_at(); + write.copy_from(bytes); + buffer_ = remain; + return true; + } + + private: + raw_span buffer_; }; } // namespace base diff --git a/naiveproxy/src/base/check.cc b/naiveproxy/src/base/check.cc index 8d90e430ba..06d303f974 100644 --- a/naiveproxy/src/base/check.cc +++ b/naiveproxy/src/base/check.cc @@ -4,6 +4,8 @@ #include "base/check.h" +#include + #include "base/check_op.h" #include "base/check_version_internal.h" #include "base/debug/alias.h" @@ -15,7 +17,13 @@ #include "base/types/cxx23_to_underlying.h" #include "build/build_config.h" -#if !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_NACL) +// Forward declaring this ptr for code simplicity below, we'll never dereference +// it under NaCl. +namespace base::debug { +class CrashKeyString; +} // namespace base::debug +#else #include "base/debug/crash_logging.h" #endif // !BUILDFLAG(IS_NACL) @@ -56,8 +64,56 @@ LogSeverity GetNotReachedSeverity(base::NotFatalUntil fatal_milestone) { return GetNotFatalUntilSeverity(fatal_milestone); } -void DumpWithoutCrashing(const std::string& crash_string, - const base::Location& location) { +base::debug::CrashKeyString* GetNotReachedCrashKey() { +#if BUILDFLAG(IS_NACL) + return nullptr; +#else + static auto* const key = ::base::debug::AllocateCrashKeyString( + "Logging-NOTREACHED_MESSAGE", base::debug::CrashKeySize::Size1024); + return key; +#endif // BUILDFLAG(IS_NACL) +} + +base::debug::CrashKeyString* GetDCheckCrashKey() { +#if BUILDFLAG(IS_NACL) + return nullptr; +#else + static auto* const key = ::base::debug::AllocateCrashKeyString( + "Logging-DCHECK_MESSAGE", base::debug::CrashKeySize::Size1024); + return key; +#endif // BUILDFLAG(IS_NACL) +} + +base::debug::CrashKeyString* GetDumpWillBeCheckCrashKey() { +#if BUILDFLAG(IS_NACL) + return nullptr; +#else + static auto* const key = ::base::debug::AllocateCrashKeyString( + "Logging-DUMP_WILL_BE_CHECK_MESSAGE", + base::debug::CrashKeySize::Size1024); + return key; +#endif // BUILDFLAG(IS_NACL) +} + +void DumpWithoutCrashing(base::debug::CrashKeyString* message_key, + const std::string& crash_string, + const base::Location& location, + base::NotFatalUntil fatal_milestone) { +#if !BUILDFLAG(IS_NACL) + static auto* const fatal_milestone_key = + ::base::debug::AllocateCrashKeyString("Logging-FATAL_MILESTONE", + base::debug::CrashKeySize::Size32); + std::optional scoped_fatal_milestone_key; + // Store the fatal milestone only when one is provided. + if (fatal_milestone != base::NotFatalUntil::NoSpecifiedMilestoneInternal) { + scoped_fatal_milestone_key.emplace( + fatal_milestone_key, + base::NumberToString(base::to_underlying(fatal_milestone))); + } + // Always store the crash string. + base::debug::ScopedCrashKeyString scoped_message_key(message_key, + crash_string); +#endif // !BUILDFLAG(IS_NACL) // Copy the crash message to stack memory to make sure it can be recovered in // crash dumps. This is easier to recover in minidumps than crash keys during // local debugging. @@ -69,54 +125,37 @@ void DumpWithoutCrashing(const std::string& crash_string, base::debug::DumpWithoutCrashing(location, base::Days(30)); } -void NotReachedDumpWithoutCrashing(const std::string& crash_string, - const base::Location& location) { -#if !BUILDFLAG(IS_NACL) - SCOPED_CRASH_KEY_STRING1024("Logging", "NOTREACHED_MESSAGE", crash_string); -#endif // !BUILDFLAG(IS_NACL) - DumpWithoutCrashing(crash_string, location); -} - -void DCheckDumpWithoutCrashing(const std::string& crash_string, - const base::Location& location) { -#if !BUILDFLAG(IS_NACL) - SCOPED_CRASH_KEY_STRING1024("Logging", "DCHECK_MESSAGE", crash_string); -#endif // !BUILDFLAG(IS_NACL) - DumpWithoutCrashing(crash_string, location); -} - -void DumpWillBeCheckDumpWithoutCrashing(const std::string& crash_string, - const base::Location& location) { -#if !BUILDFLAG(IS_NACL) - SCOPED_CRASH_KEY_STRING1024("Logging", "DUMP_WILL_BE_CHECK_MESSAGE", - crash_string); -#endif // !BUILDFLAG(IS_NACL) - DumpWithoutCrashing(crash_string, location); -} - class NotReachedLogMessage : public LogMessage { public: - NotReachedLogMessage(const base::Location& location, LogSeverity severity) + NotReachedLogMessage(const base::Location& location, + LogSeverity severity, + base::NotFatalUntil fatal_milestone) : LogMessage(location.file_name(), location.line_number(), severity), - location_(location) {} + location_(location), + fatal_milestone_(fatal_milestone) {} ~NotReachedLogMessage() override { if (severity() != logging::LOGGING_FATAL) { - NotReachedDumpWithoutCrashing(BuildCrashString(), location_); + DumpWithoutCrashing(GetNotReachedCrashKey(), BuildCrashString(), + location_, fatal_milestone_); } } private: const base::Location location_; + const base::NotFatalUntil fatal_milestone_; }; class DCheckLogMessage : public LogMessage { public: - DCheckLogMessage(const base::Location& location, LogSeverity severity) - : LogMessage(location.file_name(), location.line_number(), severity), + DCheckLogMessage(const base::Location& location) + : LogMessage(location.file_name(), + location.line_number(), + LOGGING_DCHECK), location_(location) {} ~DCheckLogMessage() override { if (severity() != logging::LOGGING_FATAL) { - DCheckDumpWithoutCrashing(BuildCrashString(), location_); + DumpWithoutCrashing(GetDCheckCrashKey(), BuildCrashString(), location_, + base::NotFatalUntil::NoSpecifiedMilestoneInternal); } } @@ -126,33 +165,38 @@ class DCheckLogMessage : public LogMessage { class CheckLogMessage : public LogMessage { public: - CheckLogMessage(const base::Location& location, LogSeverity severity) + CheckLogMessage(const base::Location& location, + LogSeverity severity, + base::NotFatalUntil fatal_milestone) : LogMessage(location.file_name(), location.line_number(), severity), - location_(location) {} + location_(location), + fatal_milestone_(fatal_milestone) {} ~CheckLogMessage() override { if (severity() != logging::LOGGING_FATAL) { - DumpWillBeCheckDumpWithoutCrashing(BuildCrashString(), location_); + DumpWithoutCrashing(GetDumpWillBeCheckCrashKey(), BuildCrashString(), + location_, fatal_milestone_); } } private: const base::Location location_; + const base::NotFatalUntil fatal_milestone_; }; #if BUILDFLAG(IS_WIN) class DCheckWin32ErrorLogMessage : public Win32ErrorLogMessage { public: DCheckWin32ErrorLogMessage(const base::Location& location, - LogSeverity severity, SystemErrorCode err) : Win32ErrorLogMessage(location.file_name(), location.line_number(), - severity, + LOGGING_DCHECK, err), location_(location) {} ~DCheckWin32ErrorLogMessage() override { if (severity() != logging::LOGGING_FATAL) { - DCheckDumpWithoutCrashing(BuildCrashString(), location_); + DumpWithoutCrashing(GetDCheckCrashKey(), BuildCrashString(), location_, + base::NotFatalUntil::NoSpecifiedMilestoneInternal); } } @@ -162,17 +206,16 @@ class DCheckWin32ErrorLogMessage : public Win32ErrorLogMessage { #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) class DCheckErrnoLogMessage : public ErrnoLogMessage { public: - DCheckErrnoLogMessage(const base::Location& location, - LogSeverity severity, - SystemErrorCode err) + DCheckErrnoLogMessage(const base::Location& location, SystemErrorCode err) : ErrnoLogMessage(location.file_name(), location.line_number(), - severity, + LOGGING_DCHECK, err), location_(location) {} ~DCheckErrnoLogMessage() override { if (severity() != logging::LOGGING_FATAL) { - DCheckDumpWithoutCrashing(BuildCrashString(), location_); + DumpWithoutCrashing(GetDCheckCrashKey(), BuildCrashString(), location_, + base::NotFatalUntil::NoSpecifiedMilestoneInternal); } } @@ -186,8 +229,8 @@ class DCheckErrnoLogMessage : public ErrnoLogMessage { CheckError CheckError::Check(const char* condition, base::NotFatalUntil fatal_milestone, const base::Location& location) { - auto* const log_message = - new CheckLogMessage(location, GetCheckSeverity(fatal_milestone)); + auto* const log_message = new CheckLogMessage( + location, GetCheckSeverity(fatal_milestone), fatal_milestone); log_message->stream() << "Check failed: " << condition << ". "; return CheckError(log_message); } @@ -195,8 +238,8 @@ CheckError CheckError::Check(const char* condition, CheckError CheckError::CheckOp(char* log_message_str, base::NotFatalUntil fatal_milestone, const base::Location& location) { - auto* const log_message = - new CheckLogMessage(location, GetCheckSeverity(fatal_milestone)); + auto* const log_message = new CheckLogMessage( + location, GetCheckSeverity(fatal_milestone), fatal_milestone); log_message->stream() << log_message_str; free(log_message_str); return CheckError(log_message); @@ -204,14 +247,14 @@ CheckError CheckError::CheckOp(char* log_message_str, CheckError CheckError::DCheck(const char* condition, const base::Location& location) { - auto* const log_message = new DCheckLogMessage(location, LOGGING_DCHECK); + auto* const log_message = new DCheckLogMessage(location); log_message->stream() << "Check failed: " << condition << ". "; return CheckError(log_message); } CheckError CheckError::DCheckOp(char* log_message_str, const base::Location& location) { - auto* const log_message = new DCheckLogMessage(location, LOGGING_DCHECK); + auto* const log_message = new DCheckLogMessage(location); log_message->stream() << log_message_str; free(log_message_str); return CheckError(log_message); @@ -219,14 +262,18 @@ CheckError CheckError::DCheckOp(char* log_message_str, CheckError CheckError::DumpWillBeCheck(const char* condition, const base::Location& location) { - auto* const log_message = new CheckLogMessage(location, GetDumpSeverity()); + auto* const log_message = + new CheckLogMessage(location, GetDumpSeverity(), + base::NotFatalUntil::NoSpecifiedMilestoneInternal); log_message->stream() << "Check failed: " << condition << ". "; return CheckError(log_message); } CheckError CheckError::DumpWillBeCheckOp(char* log_message_str, const base::Location& location) { - auto* const log_message = new CheckLogMessage(location, GetDumpSeverity()); + auto* const log_message = + new CheckLogMessage(location, GetDumpSeverity(), + base::NotFatalUntil::NoSpecifiedMilestoneInternal); log_message->stream() << log_message_str; free(log_message_str); return CheckError(log_message); @@ -254,11 +301,9 @@ CheckError CheckError::DPCheck(const char* condition, const base::Location& location) { SystemErrorCode err_code = logging::GetLastSystemErrorCode(); #if BUILDFLAG(IS_WIN) - auto* const log_message = - new DCheckWin32ErrorLogMessage(location, LOGGING_DCHECK, err_code); + auto* const log_message = new DCheckWin32ErrorLogMessage(location, err_code); #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) - auto* const log_message = - new DCheckErrnoLogMessage(location, LOGGING_DCHECK, err_code); + auto* const log_message = new DCheckErrnoLogMessage(location, err_code); #endif log_message->stream() << "Check failed: " << condition << ". "; return CheckError(log_message); @@ -266,8 +311,9 @@ CheckError CheckError::DPCheck(const char* condition, CheckError CheckError::DumpWillBeNotReachedNoreturn( const base::Location& location) { - auto* const log_message = - new NotReachedLogMessage(location, GetDumpSeverity()); + auto* const log_message = new NotReachedLogMessage( + location, GetDumpSeverity(), + base::NotFatalUntil::NoSpecifiedMilestoneInternal); log_message->stream() << "NOTREACHED hit. "; return CheckError(log_message); } @@ -305,7 +351,7 @@ CheckError::~CheckError() { NotReachedError NotReachedError::NotReached(base::NotFatalUntil fatal_milestone, const base::Location& location) { auto* const log_message = new NotReachedLogMessage( - location, GetNotReachedSeverity(fatal_milestone)); + location, GetNotReachedSeverity(fatal_milestone), fatal_milestone); // TODO(pbos): Consider a better message for NotReached(), this is here to // match existing behavior + test expectations. @@ -324,8 +370,9 @@ NotReachedError::~NotReachedError() = default; NotReachedNoreturnError::NotReachedNoreturnError(const base::Location& location) : CheckError([location]() { - auto* const log_message = - new NotReachedLogMessage(location, LOGGING_FATAL); + auto* const log_message = new NotReachedLogMessage( + location, LOGGING_FATAL, + base::NotFatalUntil::NoSpecifiedMilestoneInternal); log_message->stream() << "NOTREACHED hit. "; return log_message; }()) {} diff --git a/naiveproxy/src/base/compiler_specific.h b/naiveproxy/src/base/compiler_specific.h index 63f003a1a6..c7dd9ab101 100644 --- a/naiveproxy/src/base/compiler_specific.h +++ b/naiveproxy/src/base/compiler_specific.h @@ -405,7 +405,7 @@ inline constexpr bool AnalyzerAssumeTrue(bool arg) { // Marks a member function as reinitializing a moved-from variable. // See also -// https://clang.llvm.org/extra/clang-tidy/checks/bugprone-use-after-move.html#reinitialization +// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/use-after-move.html#reinitialization #if defined(__clang__) && HAS_ATTRIBUTE(reinitializes) #define REINITIALIZES_AFTER_MOVE [[clang::reinitializes]] #else @@ -443,15 +443,87 @@ inline constexpr bool AnalyzerAssumeTrue(bool arg) { // Additionally, the initial implementation in clang <= 16 overwrote the return // register(s) in the epilogue of a preserve_most function, so we only use // preserve_most in clang >= 17 (see https://reviews.llvm.org/D143425). +// Clang only supports preserve_most on X86-64 and AArch64 for now. // See https://clang.llvm.org/docs/AttributeReference.html#preserve-most for // more details. -#if defined(ARCH_CPU_64_BITS) && \ - !(BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)) && \ - !defined(COMPONENT_BUILD) && defined(__clang__) && \ +#if (defined(ARCH_CPU_ARM64) || defined(ARCH_CPU_X86_64)) && \ + !(BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)) && \ + !defined(COMPONENT_BUILD) && defined(__clang__) && \ __clang_major__ >= 17 && HAS_ATTRIBUTE(preserve_most) #define PRESERVE_MOST __attribute__((preserve_most)) #else #define PRESERVE_MOST #endif +// Functions should be marked with UNSAFE_BUFFER_USAGE when they lead to +// out-of-bounds bugs when called with incorrect inputs. +// +// Ideally such functions should be paired with a safer version that works with +// safe primitives like `base::span`. Otherwise, another safer coding pattern +// should be documented along side the use of `UNSAFE_BUFFER_USAGE`. +// +// All functions marked with UNSAFE_BUFFER_USAGE should come with a safety +// comment that explains the requirements of the function to prevent any chance +// of an out-of-bounds bug. For example: +// ``` +// // Function to do things between `input` and `end`. +// // +// // # Safety +// // The `input` must point to an array with size at least 5. The `end` must +// // point within the same allocation of `input` and not come before `input`. +// ``` +#if defined(__clang__) && HAS_ATTRIBUTE(unsafe_buffer_usage) +#define UNSAFE_BUFFER_USAGE [[clang::unsafe_buffer_usage]] +#else +#define UNSAFE_BUFFER_USAGE +#endif + +// UNSAFE_BUFFERS() wraps code that violates the -Wunsafe-buffer-usage warning, +// such as: +// - pointer arithmetic, +// - pointer subscripting, and +// - calls to functions annotated with UNSAFE_BUFFER_USAGE. +// +// ** USE OF THIS MACRO SHOULD BE VERY RARE.** Reviewers should push back when +// it is not strictly necessary. Prefer to use `base::span` instead of pointers, +// or other safer coding patterns (like std containers) that avoid the +// opportunity for out-of-bounds bugs to creep into the code. Any use of +// UNSAFE_BUFFERS() can lead to a critical security bug if any assumptions are +// wrong, or ever become wrong in the future. +// +// The macro should be used to wrap the minimum necessary code, to make it clear +// what is unsafe, and prevent accidentally opting extra things out of the +// warning. +// +// All usage of UNSAFE_BUFFERS() should come with a `// SAFETY: ...` comment +// that explains how we have guaranteed (ideally directly above, with conditions +// or CHECKs) that the pointer usage can never go out-of-bounds, or that the +// requirements of the UNSAFE_BUFFER_USAGE function are met. If the safety +// explanation requires cooperation of code that is not fully encapsulated close +// to the UNSAFE_BUFFERS() usage, it should be rejected and replaced with safer +// coding patterns or stronger guarantees. +// +// UNSAFE_BUFFERS_INCLUDE_BEGIN / UNSAFE_BUFFERS_INCLUDE_END can be used to +// wrap an `#include` statement for a header which has not been made clean for +// the -Wunsafe-buffer-usage warning. As these disable warnings for the entire +// header, and its transitive dependencies, it's clear these should be temporary +// and the header converted to use safe operations via `span` (or use +// UNSAFE_BUFFERS() explicitly in rare cases). +#if defined(__clang__) +// clang-format off +// Formatting is off so that we can put each _Pragma on its own line, as +// recommended by the gcc docs. +#define UNSAFE_BUFFERS(...) \ + _Pragma("clang unsafe_buffer_usage begin") \ + __VA_ARGS__ \ + _Pragma("clang unsafe_buffer_usage end") +// clang-format on +#define UNSAFE_BUFFERS_INCLUDE_BEGIN _Pragma("clang unsafe_buffer_usage begin") +#define UNSAFE_BUFFERS_INCLUDE_END _Pragma("clang unsafe_buffer_usage end") +#else +#define UNSAFE_BUFFERS(...) __VA_ARGS__ +#define UNSAFE_BUFFERS_INCLUDE_BEGIN +#define UNSAFE_BUFFERS_INCLUDE_END +#endif + #endif // BASE_COMPILER_SPECIFIC_H_ diff --git a/naiveproxy/src/base/containers/buffer_iterator.h b/naiveproxy/src/base/containers/buffer_iterator.h index 9fdcabaf29..d491737f6d 100644 --- a/naiveproxy/src/base/containers/buffer_iterator.h +++ b/naiveproxy/src/base/containers/buffer_iterator.h @@ -7,12 +7,12 @@ #include -#include +#include +#include -#include "base/bit_cast.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/numerics/checked_math.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { @@ -58,48 +58,75 @@ namespace base { template class BufferIterator { public: - static_assert(std::is_same_v, char> || - std::is_same_v, unsigned char>, + static_assert(std::same_as, char> || + std::same_as, unsigned char>, "Underlying buffer type must be char-type."); - + // Constructs an empty BufferIterator that will always return null pointers. BufferIterator() {} - BufferIterator(B* data, size_t size) - : BufferIterator(make_span(data, size)) {} + + // Constructs a BufferIterator over the `buffer` span, that will return + // pointers into the span. explicit BufferIterator(span buffer) : buffer_(buffer), remaining_(buffer) {} - ~BufferIterator() {} - // Returns a pointer to a mutable structure T in the buffer at the current - // position. On success, the iterator position is advanced by sizeof(T). If - // there are not sizeof(T) bytes remaining in the buffer, returns nullptr. + // TODO(crbug.com/40284755): Move all callers to use spans and remove this. + UNSAFE_BUFFER_USAGE BufferIterator(B* data, size_t size) + : BufferIterator( + // TODO(crbug.com/40284755): Remove this constructor entirely, + // callers should provide a span. There's no way to know that the + // size is correct here. + UNSAFE_BUFFERS(span(data, size))) {} + + // Copies out an object. As compared to using `Object`, this avoids potential + // unaligned access which may be undefined behavior. template >> - T* MutableObject() { - size_t size = sizeof(T); - if (size > remaining_.size()) - return nullptr; - T* t = reinterpret_cast(remaining_.data()); - remaining_ = remaining_.subspan(size); + std::optional CopyObject() { + std::optional t; + if (remaining_.size() >= sizeof(T)) { + auto [source, remain] = remaining_.template split_at(); + byte_span_from_ref(t.emplace()).copy_from(as_bytes(source)); + remaining_ = remain; + } return t; } // Returns a const pointer to an object of type T in the buffer at the current // position. + // + // # Safety + // Note that the buffer's current position must be aligned for the type T + // or using the pointer will cause Undefined Behaviour. Generally prefer + // `CopyObject` as it avoids this problem entirely. + // TODO(danakj): We should probably CHECK this instead of allowing UB into + // production. template >> const T* Object() { return MutableObject(); } - // Copies out an object. As compared to using Object, this avoids potential - // unaligned access which may be undefined behavior. + // Returns a pointer to a mutable structure T in the buffer at the current + // position. On success, the iterator position is advanced by sizeof(T). If + // there are not sizeof(T) bytes remaining in the buffer, returns nullptr. + // + // # Safety + // Note that the buffer's current position must be aligned for the type T or + // using the pointer will cause Undefined Behaviour. Generally prefer + // `CopyObject` as it avoids this problem entirely. + // TODO(danakj): We should probably CHECK this instead of allowing UB into + // production. template >> - absl::optional CopyObject() { - absl::optional t; + T* MutableObject() { + T* t = nullptr; if (remaining_.size() >= sizeof(T)) { - memcpy(&t.emplace(), remaining_.data(), sizeof(T)); - remaining_ = remaining_.subspan(sizeof(T)); + auto [source, remain] = remaining_.template split_at(); + // TODO(danakj): This is UB without creating a lifetime for the object in + // the compiler, which we can not do before C++23: + // https://en.cppreference.com/w/cpp/memory/start_lifetime_as + t = reinterpret_cast(source.data()); + remaining_ = remain; } return t; } @@ -108,21 +135,41 @@ class BufferIterator { // On success, the iterator position is advanced by |sizeof(T) * count|. If // there are not enough bytes remaining in the buffer to fulfill the request, // returns an empty span. + // + // # Safety + // Note that the buffer's current position must be aligned for the type T or + // using the span will cause Undefined Behaviour. + // TODO(danakj): We should probably CHECK this instead of allowing UB into + // production. template >> span MutableSpan(size_t count) { - size_t size; - if (!CheckMul(sizeof(T), count).AssignIfValid(&size)) + size_t byte_size; + if (!CheckMul(sizeof(T), count).AssignIfValid(&byte_size)) { return span(); - if (size > remaining_.size()) + } + if (byte_size > remaining_.size()) { return span(); - auto result = span(reinterpret_cast(remaining_.data()), count); - remaining_ = remaining_.subspan(size); - return result; + } + auto [lhs, rhs] = remaining_.split_at(byte_size); + remaining_ = rhs; + // SAFETY: The byte size of `span` with size `count` is `count * + // sizeof(T)` which is exactly `byte_size`, the byte size of `lhs`. + // + // TODO(danakj): This is UB without creating a lifetime for the object in + // the compiler, which we can not do before C++23: + // https://en.cppreference.com/w/cpp/memory/start_lifetime_as + return UNSAFE_BUFFERS(span(reinterpret_cast(lhs.data()), count)); } // Returns a span to |count| const objects of type T in the buffer at the // current position. + // + // # Safety + // Note that the buffer's current position must be aligned for the type T or + // using the span will cause Undefined Behaviour. + // TODO(danakj): We should probably CHECK this instead of allowing UB into + // production. template >> span Span(size_t count) { @@ -141,15 +188,18 @@ class BufferIterator { // Returns the current position in the buffer. size_t position() const { - DCHECK(buffer_.data() <= remaining_.data()); - DCHECK(remaining_.data() <= buffer_.data() + buffer_.size()); - return static_cast(remaining_.data() - buffer_.data()); + // SAFETY: `remaining_` is a subspan always constructed from `buffer_` (or + // from itself) so its `data()` pointer is always inside `buffer_`. This + // means the subtraction is well-defined and the result is always + // non-negative. + return static_cast( + UNSAFE_BUFFERS(remaining_.data() - buffer_.data())); } private: // The original buffer that the iterator was constructed with. const span buffer_; - // A subspan of |buffer_| containing the remaining bytes to iterate over. + // A subspan of `buffer_` containing the remaining bytes to iterate over. span remaining_; // Copy and assign allowed. }; diff --git a/naiveproxy/src/base/containers/checked_iterators.h b/naiveproxy/src/base/containers/checked_iterators.h index dbef27ae59..6f62aa8174 100644 --- a/naiveproxy/src/base/containers/checked_iterators.h +++ b/naiveproxy/src/base/containers/checked_iterators.h @@ -11,6 +11,7 @@ #include #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/util.h" #include "base/memory/raw_ptr_exclusion.h" #include "build/build_config.h" @@ -38,10 +39,13 @@ class CheckedContiguousIterator { constexpr CheckedContiguousIterator() = default; - constexpr CheckedContiguousIterator(T* start, const T* end) + UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(T* start, + const T* end) : CheckedContiguousIterator(start, start, end) {} - constexpr CheckedContiguousIterator(const T* start, T* current, const T* end) + UNSAFE_BUFFER_USAGE constexpr CheckedContiguousIterator(const T* start, + T* current, + const T* end) : start_(start), current_(current), end_(end) { CHECK_LE(start, current); CHECK_LE(current, end); diff --git a/naiveproxy/src/base/containers/enum_set.h b/naiveproxy/src/base/containers/enum_set.h index 885fbb4cfb..051f379423 100644 --- a/naiveproxy/src/base/containers/enum_set.h +++ b/naiveproxy/src/base/containers/enum_set.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -306,6 +307,8 @@ class EnumSet { // Returns true iff our set and the given set contain exactly the same values. friend bool operator==(const EnumSet&, const EnumSet&) = default; + std::string ToString() const { return enums_.to_string(); } + private: friend constexpr EnumSet Union(EnumSet set1, EnumSet set2); diff --git a/naiveproxy/src/base/containers/fixed_flat_map.h b/naiveproxy/src/base/containers/fixed_flat_map.h index df048f06f1..3f74b78b8e 100644 --- a/naiveproxy/src/base/containers/fixed_flat_map.h +++ b/naiveproxy/src/base/containers/fixed_flat_map.h @@ -93,7 +93,7 @@ using fixed_flat_map = base:: // of keys and values. Requires that the passed in `data` contains unique keys. // // Large inputs will run into compiler limits, e.g. "constexpr evaluation hit -// maximum step limit". In that case, use `MakeFixedFlatMap(sorted_unique)`. +// maximum step limit", unless `data` is already sorted. // // Example usage: // constexpr auto kMap = base::MakeFixedFlatMap( diff --git a/naiveproxy/src/base/containers/heap_array.h b/naiveproxy/src/base/containers/heap_array.h index 9bec60da00..f9187e84be 100644 --- a/naiveproxy/src/base/containers/heap_array.h +++ b/naiveproxy/src/base/containers/heap_array.h @@ -163,6 +163,15 @@ class TRIVIAL_ABI GSL_OWNER HeapArray { return as_span().last(count); } + // Leaks the memory in the HeapArray so that it will never be freed, and + // consumes the HeapArray, returning an unowning span that points to the + // memory. + base::span leak() && { + HeapArray dropped = std::move(*this); + T* leaked = dropped.data_.release(); + return make_span(leaked, dropped.size_); + } + private: HeapArray(std::unique_ptr data, size_t size) : data_(std::move(data)), size_(size) {} diff --git a/naiveproxy/src/base/containers/span.h b/naiveproxy/src/base/containers/span.h index 3879f2d40c..4fb57f8e74 100644 --- a/naiveproxy/src/base/containers/span.h +++ b/naiveproxy/src/base/containers/span.h @@ -14,12 +14,17 @@ #include #include #include +#include #include #include #include "base/check.h" #include "base/compiler_specific.h" +// TODO(crbug.com/40284755): checked_iterators should use UNSAFE_BUFFERS() +// internally. +UNSAFE_BUFFERS_INCLUDE_BEGIN #include "base/containers/checked_iterators.h" +UNSAFE_BUFFERS_INCLUDE_END #include "base/numerics/safe_conversions.h" #include "base/template_util.h" #include "third_party/abseil-cpp/absl/base/attributes.h" @@ -140,6 +145,29 @@ constexpr size_t must_not_be_dynamic_extent() { // char str_buffer[100]; // SafeSNPrintf(str_buffer, "Pi ~= %lf", 3.14); // +// Dynamic vs Fixed size spans +// --------------------------- +// +// Normally spans have a dynamic size, which is represented as a type as +// `span`. However it is possible to encode the size of the span into the +// type as a second parameter such as `span`. When working with fixed-size +// spans, the compiler will check the size of operations and prevent compilation +// when an invalid size is used for an operation such as assignment or +// `copy_from()`. However operations that produce a new span will make a +// dynamic-sized span by default. See below for how to prevent that. +// +// Fixed-size spans implicitly convert to a dynamic-size span, throwing away the +// compile-time size information from the type signature. So most code should +// work with dynamic-sized `span` types and not worry about the existence of +// fixed-size spans. +// +// It is possible to convert from a dynamic-size to a fixed-size span (or to +// move from a fixed-size span to another fixed-size span) but it requires +// writing an the size explicitly in the code. Methods like `first` can be +// passed a size as a template argument, such as `first()` to generate a +// fixed-size span. And the `make_span` function can be given a compile-time +// size in a similar way with `make_span()`. +// // Spans with "const" and pointers // ------------------------------- // @@ -183,13 +211,22 @@ constexpr size_t must_not_be_dynamic_extent() { // Differences from [span.deduct]: // - The deduction guides from a contiguous range are folded into a single one, // and treat borrowed ranges correctly. +// - Add deduction guide from rvalue array. +// +// Other differences: +// - Using StrictNumeric instead of size_t where possible. // // Additions beyond the C++ standard draft // - as_chars() function. // - as_writable_chars() function. // - as_byte_span() function. +// - as_writable_byte_span() function. // - copy_from() method. // - span_from_ref() function. +// - byte_span_from_ref() function. +// - span_from_cstring() function. +// - byte_span_from_cstring() function. +// - split_at() method. // // Furthermore, all constructors and methods are marked noexcept due to the lack // of exceptions in Chromium. @@ -218,9 +255,21 @@ class GSL_POINTER span { requires(N == 0) = default; + // Constructs a span from a contiguous iterator and a size. + // + // # Checks + // The function CHECKs that `count` matches the template parameter `N` and + // will terminate otherwise. + // + // # Safety + // The iterator must point to the first of at least `count` many elements, or + // Undefined Behaviour can result as the span will allow access beyond the + // valid range of the collection pointed to by the iterator. template requires(internal::CompatibleIter) - explicit constexpr span(It first, StrictNumeric count) noexcept + UNSAFE_BUFFER_USAGE explicit constexpr span( + It first, + StrictNumeric count) noexcept : // The use of to_address() here is to handle the case where the // iterator `first` is pointing to the container's `end()`. In that // case we can not use the address returned from the iterator, or @@ -242,39 +291,102 @@ class GSL_POINTER span { // being passed in, since we have no context to determine if the // iterator or count are valid. data_(std::to_address(first)) { + // Guarantees that the N in the type signature is correct. CHECK(N == count); } + // Constructs a span from a contiguous iterator and a size. + // + // # Checks + // The function CHECKs that `it <= end` and will terminate otherwise. + // + // # Safety + // The begin and end iterators must be for the same allocation or Undefined + // Behaviour can result as the span will allow access beyond the valid range + // of the collection pointed to by `begin`. template requires(internal::CompatibleIter && std::sized_sentinel_for && !std::convertible_to) - explicit constexpr span(It begin, End end) noexcept - : span(begin, static_cast(end - begin)) {} + UNSAFE_BUFFER_USAGE explicit constexpr span(It begin, End end) noexcept + // SAFETY: The caller must guarantee that the iterator and end sentinel + // are part of the same allocation, in which case it is the number of + // elements between the iterators and thus a valid size for the pointer to + // the element at `begin`. + // + // We CHECK that `end - begin` did not underflow below. Normally checking + // correctness afterward is flawed, however underflow is not UB and the + // size is not converted to an invalid pointer (which would be UB) before + // we CHECK for underflow. + : UNSAFE_BUFFERS(span(begin, static_cast(end - begin))) { + // Verify `end - begin` did not underflow. + CHECK(begin <= end); + } // NOLINTNEXTLINE(google-explicit-constructor) constexpr span(T (&arr)[N]) noexcept - : span(std::ranges::data(arr), std::ranges::size(arr)) {} + // SAFETY: The std::ranges::size() function gives the number of elements + // pointed to by the std::ranges::data() function, which meets the + // requirement of span. + : UNSAFE_BUFFERS(span(std::ranges::data(arr), std::ranges::size(arr))) {} template > requires(internal::CompatibleRange && (X == N || X == dynamic_extent)) // NOLINTNEXTLINE(google-explicit-constructor) explicit(X == dynamic_extent) constexpr span(R&& range) noexcept - : span(std::ranges::data(range), std::ranges::size(range)) {} + // SAFETY: The std::ranges::size() function gives the number of elements + // pointed to by the std::ranges::data() function, which meets the + // requirement of span. + : UNSAFE_BUFFERS( + span(std::ranges::data(range), std::ranges::size(range))) {} // [span.sub], span subviews template constexpr span first() const noexcept requires(Count <= N) { - return span(data(), Count); + // SAFETY: span provides that data() points to at least `N` many elements. + // `Count` is non-negative by its type and `Count <= N` from the requires + // condition. So `Count` is a valid new size for `data()`. + return UNSAFE_BUFFERS(span(data(), Count)); } template constexpr span last() const noexcept requires(Count <= N) { - return span(data() + (size() - Count), Count); + // SAFETY: span provides that data() points to at least `N` many elements. + // `Count` is non-negative by its type and `Count <= N` from the requires + // condition. So `0 <= N - Count <= N`, meaning `N - Count` is a valid new + // size for `data()` and it will point to `Count` many elements.` + return UNSAFE_BUFFERS(span(data() + (N - Count), Count)); + } + + // Returns a span over the first `count` elements. + // + // # Checks + // The function CHECKs that the span contains at least `count` elements and + // will terminate otherwise. + constexpr span first(StrictNumeric count) const noexcept { + CHECK_LE(size_t{count}, size()); + // SAFETY: span provides that data() points to at least `N` many elements. + // `count` is non-negative by its type and `count <= N` from the CHECK + // above. So `count` is a valid new size for `data()`. + return UNSAFE_BUFFERS({data(), count}); + } + + // Returns a span over the last `count` elements. + // + // # Checks + // The function CHECKs that the span contains at least `count` elements and + // will terminate otherwise. + constexpr span last(StrictNumeric count) const noexcept { + CHECK_LE(size_t{count}, N); + // SAFETY: span provides that data() points to at least `N` many elements. + // `count` is non-negative by its type and `count <= N` from the CHECK + // above. So `0 <= N - count <= N`, meaning `N - count` is a valid new size + // for `data()` and it will point to `count` many elements. + return UNSAFE_BUFFERS({data() + (N - size_t{count}), count}); } template @@ -282,25 +394,81 @@ class GSL_POINTER span { requires(Offset <= N && (Count == dynamic_extent || Count <= N - Offset)) { constexpr size_t kExtent = Count != dynamic_extent ? Count : N - Offset; - return span(data() + Offset, kExtent); + // SAFETY: span provides that data() points to at least `N` many elements. + // + // If Count is dynamic_extent, kExtent becomes `N - Offset`. Since `Offset + // <= N` from the requires condition, then `Offset` is a valid offset for + // data(), and `Offset + kExtent = Offset + N - Offset = N >= Offset` is + // also a valid offset that is not before `Offset`. This makes a span at + // `Offset` with size `kExtent` valid. + // + // Otherwise `Count <= N - Offset` and `0 <= Offset <= N` by the requires + // condition, so `Offset <= N - Count` and `N - Count` can not underflow. + // Then `Offset` is a valid offset for data() and `kExtent` is `Count <= N - + // Offset`, so `Offset + kExtent <= Offset + N - Offset = N` which makes + // both `Offset` and `Offset + kExtent` valid offsets for data(), and since + // `kExtent` is non-negative, `Offset + kExtent` is not before `Offset` so + // `kExtent` is a valid size for the span at `data() + Offset`. + return UNSAFE_BUFFERS(span(data() + Offset, kExtent)); } - constexpr span first(size_t count) const noexcept { - CHECK_LE(count, size()); - return {data(), count}; + // Returns a span over the first `count` elements starting at the given + // `offset` from the start of the span. + // + // # Checks + // The function CHECKs that the span contains at least `offset + count` + // elements, or at least `offset` elements if `count` is not specified, and + // will terminate otherwise. + constexpr span subspan(size_t offset, + size_t count = dynamic_extent) const noexcept { + CHECK_LE(offset, N); + CHECK(count == dynamic_extent || count <= N - offset); + const size_t new_extent = count != dynamic_extent ? count : N - offset; + // SAFETY: span provides that data() points to at least `N` many elements. + // + // If Count is dynamic_extent, `new_extent` becomes `N - offset`. Since + // `offset <= N` from the requires condition, then `offset` is a valid + // offset for data(), and `offset + new_extent = offset + N - offset = N >= + // offset` is also a valid offset that is not before `offset`. This makes a + // span at `offset` with size `new_extent` valid. + // + // Otherwise `count <= N - offset` and `0 <= offset <= N` by the requires + // condition, so `offset <= N - count` and `N - count` can not underflow. + // Then `offset` is a valid offset for data() and `new_extent` is `count <= + // N - offset`, so `offset + new_extent <= offset + N - offset = N` which + // makes both `offset` and `offset + new_extent` valid offsets for data(), + // and since `new_extent` is non-negative, `offset + new_extent` is not + // before `offset` so `new_extent` is a valid size for the span at `data() + + // offset`. + return UNSAFE_BUFFERS({data() + offset, new_extent}); } - constexpr span last(size_t count) const noexcept { - CHECK_LE(count, size()); - return {data() + (size() - count), count}; + // Splits a span into two at the given `offset`, returning two spans that + // cover the full range of the original span. + // + // Similar to calling subspan() with the `offset` as the length on the first + // call, and then the `offset` as the offset in the second. + // + // The split_at() overload allows construction of a fixed-size span from a + // compile-time constant. If the input span is fixed-size, both output output + // spans will be. Otherwise, the first will be fixed-size and the second will + // be dynamic-size. + // + // This is a non-std extension that is inspired by the Rust slice::split_at() + // and split_at_mut() methods. + // + // # Checks + // The function CHECKs that the span contains at least `offset` elements and + // will terminate otherwise. + constexpr std::pair, span> split_at(size_t offset) const noexcept { + return {first(offset), subspan(offset)}; } - constexpr span subspan( - size_t offset, - size_t count = dynamic_extent) const noexcept { - CHECK_LE(offset, size()); - CHECK(count == dynamic_extent || count <= size() - offset); - return {data() + offset, count != dynamic_extent ? count : size() - offset}; + template + requires(Offset <= N) + constexpr std::pair, span> split_at() + const noexcept { + return {first(), subspan()}; } // [span.obs], span observers @@ -309,32 +477,55 @@ class GSL_POINTER span { [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access + // + // # Checks + // The function CHECKs that the `idx` is inside the span and will terminate + // otherwise. constexpr T& operator[](size_t idx) const noexcept { CHECK_LT(idx, size()); - return data()[idx]; + // SAFETY: Since data() always points to at least `N` elements, the check + // above ensures `idx < N` and is thus in range for data(). + return UNSAFE_BUFFERS(data()[idx]); } constexpr T& front() const noexcept requires(N > 0) { - return data()[0]; + // SAFETY: Since data() always points to at least `N` elements, the requires + // constraint above ensures `0 < N` and is thus in range for data(). + return UNSAFE_BUFFERS(data()[0]); } constexpr T& back() const noexcept requires(N > 0) { - return data()[size() - 1]; + // SAFETY: Since data() always points to at least `N` elements, the requires + // constraint above ensures `N > 0` and thus `N - 1` does not underflow and + // is in range for data(). + return UNSAFE_BUFFERS(data()[N - 1]); } + // Returns a pointer to the first element in the span. If the span is empty + // (`size()` is 0), the returned pointer may or may not be null, and it must + // not be dereferenced. + // + // It is always valid to add `size()` to the the pointer in C++ code, though + // it may be invalid in C code when the span is empty. constexpr T* data() const noexcept { return data_; } // [span.iter], span iterator support constexpr iterator begin() const noexcept { - return iterator(data(), data() + size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements, and size() is non-negative. So data() + size() is a valid + // pointer for the data() allocation. + return UNSAFE_BUFFERS(iterator(data(), data() + size())); } constexpr iterator end() const noexcept { - return iterator(data(), data() + size(), data() + size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements, and size() is non-negative. So data() + size() is a valid + // pointer for the data() allocation. + return UNSAFE_BUFFERS(iterator(data(), data() + size(), data() + size())); } constexpr reverse_iterator rbegin() const noexcept { @@ -345,22 +536,71 @@ class GSL_POINTER span { return reverse_iterator(begin()); } - // Bounds-checked copy of spans into spans. The spans must be the exact - // same size or a hard CHECK() occurs. This is a non-std extension that - // is inspired by the Rust slice::copy_from_slice() method. - template - void copy_from(const span& other) - requires(M != dynamic_extent && internal::LegalDataConversion) - { - static_assert(N == M, "span size mismatch"); - std::ranges::copy(other, data()); - } - template - void copy_from(const span& other) - requires(M == dynamic_extent && internal::LegalDataConversion) - { + // Bounds-checked copy from a non-overlapping span. The spans must be the + // exact same size or a hard CHECK() occurs. If the two spans overlap, + // Undefined Behaviour occurs. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // # Checks + // The function CHECKs that the `other` span has the same size as itself and + // will terminate otherwise. + constexpr void copy_from(span other) { CHECK_EQ(size_bytes(), other.size_bytes()); - std::ranges::copy(other, data()); + // Verify non-overlapping in developer builds. + // + // SAFETY: span provides that data() points to at least size() many + // elements, so adding size() to the data() pointer is well-defined. + DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() || + data() >= UNSAFE_BUFFERS(other.data() + other.size())); + // When compiling with -Oz, std::ranges::copy() does not get inlined, which + // makes copy_from() very expensive compared to memcpy for small sizes (up + // to around 4x slower). We observe that this is because ranges::copy() uses + // begin()/end() and span's iterators are checked iterators, not just + // pointers. This additional complexity prevents inlining and breaks the + // ability for the compiler to eliminate code. + // + // See also https://crbug.com/1396134. + // + // We also see std::copy() (with pointer arguments! not iterators) optimize + // and inline better than memcpy() since memcpy() needs to rely on + // size_bytes(), which while computable at compile time when `other` has a + // fixed size, the optimizer stumbles on with -Oz. + // + // SAFETY: The copy() here does not check bounds, but we have verified that + // `this` and `other` have the same bounds above (and are pointers of the + // same type), so `data()` and `other.data()` both have at least + // `other.size()` elements. + UNSAFE_BUFFERS( + std::copy(other.data(), other.data() + other.size(), data())); + } + + // Implicit conversion from std::span to base::span. + // + // We get other conversions for free from std::span's constructors, but it + // does not deduce N on its range constructor. + span(std::span, N> other) + : // SAFETY: std::span contains a valid data pointer and size such + // that pointer+size remains valid. + UNSAFE_BUFFERS( + span(std::ranges::data(other), std::ranges::size(other))) {} + span(std::span other) + requires(std::is_const_v) + : // SAFETY: std::span contains a valid data pointer and size such + // that pointer+size remains valid. + UNSAFE_BUFFERS( + span(std::ranges::data(other), std::ranges::size(other))) {} + + // Implicit conversion from base::span to std::span. + // + // We get other conversions for free from std::span's constructors, but it + // does not deduce N on its range constructor. + operator std::span() const { return std::span(*this); } + operator std::span() const + requires(!std::is_const_v) + { + return std::span(*this); } private: @@ -387,9 +627,16 @@ class GSL_POINTER span { constexpr span() noexcept = default; + // Constructs a span from a contiguous iterator and a size. + // + // # Safety + // The iterator must point to the first of at least `count` many elements, or + // Undefined Behaviour can result as the span will allow access beyond the + // valid range of the collection pointed to by the iterator. template requires(internal::CompatibleIter) - constexpr span(It first, StrictNumeric count) noexcept + UNSAFE_BUFFER_USAGE constexpr span(It first, + StrictNumeric count) noexcept // The use of to_address() here is to handle the case where the iterator // `first` is pointing to the container's `end()`. In that case we can // not use the address returned from the iterator, or dereference it @@ -411,65 +658,185 @@ class GSL_POINTER span { // iterator or count are valid. : data_(std::to_address(first)), size_(count) {} + // Constructs a span from a contiguous iterator and a size. + // + // # Safety + // The begin and end iterators must be for the same allocation, and `begin <= + // end` or Undefined Behaviour can result as the span will allow access beyond + // the valid range of the collection pointed to by `begin`. template requires(internal::CompatibleIter && std::sized_sentinel_for && !std::convertible_to) - constexpr span(It begin, End end) noexcept - // Subtracting two iterators gives a ptrdiff_t, but the result should be - // non-negative: see CHECK below. - : span(begin, static_cast(end - begin)) { + UNSAFE_BUFFER_USAGE constexpr span(It begin, End end) noexcept + // SAFETY: The caller must guarantee that the iterator and end sentinel + // are part of the same allocation, in which case it is the number of + // elements between the iterators and thus a valid size for the pointer to + // the element at `begin`. + // + // We CHECK that `end - begin` did not underflow below. Normally checking + // correctness afterward is flawed, however underflow is not UB and the + // size is not converted to an invalid pointer (which would be UB) before + // we CHECK for underflow. + : UNSAFE_BUFFERS(span(begin, static_cast(end - begin))) { + // Verify `end - begin` did not underflow. CHECK(begin <= end); } template // NOLINTNEXTLINE(google-explicit-constructor) constexpr span(T (&arr)[N]) noexcept - : span(std::ranges::data(arr), std::ranges::size(arr)) {} + // SAFETY: The std::ranges::size() function gives the number of elements + // pointed to by the std::ranges::data() function, which meets the + // requirement of span. + : UNSAFE_BUFFERS(span(std::ranges::data(arr), std::ranges::size(arr))) {} template requires(internal::LegacyCompatibleRange) // NOLINTNEXTLINE(google-explicit-constructor) constexpr span(R&& range) noexcept - : span(std::ranges::data(range), std::ranges::size(range)) {} + // SAFETY: The std::ranges::size() function gives the number of elements + // pointed to by the std::ranges::data() function, which meets the + // requirement of span. + : UNSAFE_BUFFERS( + span(std::ranges::data(range), std::ranges::size(range))) {} // [span.sub], span subviews template constexpr span first() const noexcept { CHECK_LE(Count, size()); - return span(data(), Count); + // SAFETY: span provides that data() points to at least `size()` many + // elements. `Count` is non-negative by its type and `Count <= size()` from + // the CHECK above. So `Count` is a valid new size for `data()`. + return UNSAFE_BUFFERS(span(data(), Count)); } template constexpr span last() const noexcept { CHECK_LE(Count, size()); - return span(data() + (size() - Count), Count); + // SAFETY: span provides that data() points to at least `size()` many + // elements. `Count` is non-negative by its type and `Count <= size()` from + // the check above. So `0 <= size() - Count <= size()`, meaning + // `size() - Count` is a valid new size for `data()` and it will point to + // `Count` many elements. + return UNSAFE_BUFFERS(span(data() + (size() - Count), Count)); + } + + // Returns a span over the first `count` elements. + // + // # Checks + // The function CHECKs that the span contains at least `count` elements and + // will terminate otherwise. + constexpr span first(StrictNumeric count) const noexcept { + CHECK_LE(size_t{count}, size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements. `count` is non-negative by its type and `count <= size()` from + // the CHECK above. So `count` is a valid new size for `data()`. + return UNSAFE_BUFFERS({data(), count}); + } + + // Returns a span over the last `count` elements. + // + // # Checks + // The function CHECKs that the span contains at least `count` elements and + // will terminate otherwise. + constexpr span last(StrictNumeric count) const noexcept { + CHECK_LE(size_t{count}, size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements. `count` is non-negative by its type and `count <= size()` from + // the CHECK above. So `0 <= size() - count <= size()`, meaning + // `size() - count` is a valid new size for `data()` and it will point to + // `count` many elements. + return UNSAFE_BUFFERS({data() + (size() - size_t{count}), count}); } template constexpr span subspan() const noexcept { CHECK_LE(Offset, size()); CHECK(Count == dynamic_extent || Count <= size() - Offset); - return span(data() + Offset, - Count != dynamic_extent ? Count : size() - Offset); + const size_t new_extent = Count != dynamic_extent ? Count : size() - Offset; + // SAFETY: span provides that data() points to at least `size()` many + // elements. + // + // If Count is dynamic_extent, `new_extent` becomes `size() - Offset`. Since + // `Offset <= size()` from the check above, then `Offset` is a valid offset + // for data(), and `Offset + new_extent = Offset + size() - Offset = size() + // >= Offset` is also a valid offset that is not before `Offset`. This makes + // a span at `Offset` with size `new_extent` valid. + // + // Otherwise `Count <= size() - Offset` and `0 <= Offset <= size()` by the + // check above, so `Offset <= size() - Count` and `size() - Count` can not + // underflow. Then `Offset` is a valid offset for data() and `new_extent` is + // `Count <= size() - Offset`, so `Offset + extent <= Offset + size() - + // Offset = size()` which makes both `Offset` and `Offset + new_extent` + // valid offsets for data(), and since `new_extent` is non-negative, `Offset + // + new_extent` is not before `Offset` so `new_extent` is a valid size for + // the span at `data() + Offset`. + return UNSAFE_BUFFERS(span(data() + Offset, new_extent)); } - constexpr span first(size_t count) const noexcept { - CHECK_LE(count, size()); - return {data(), count}; - } - - constexpr span last(size_t count) const noexcept { - CHECK_LE(count, size()); - return {data() + (size() - count), count}; - } - - constexpr span subspan( - size_t offset, - size_t count = dynamic_extent) const noexcept { + // Returns a span over the first `count` elements starting at the given + // `offset` from the start of the span. + // + // # Checks + // The function CHECKs that the span contains at least `offset + count` + // elements, or at least `offset` elements if `count` is not specified, and + // will terminate otherwise. + constexpr span subspan(size_t offset, + size_t count = dynamic_extent) const noexcept { CHECK_LE(offset, size()); CHECK(count == dynamic_extent || count <= size() - offset); - return {data() + offset, count != dynamic_extent ? count : size() - offset}; + const size_t new_extent = count != dynamic_extent ? count : size() - offset; + // SAFETY: span provides that data() points to at least `size()` many + // elements. + // + // If count is dynamic_extent, `new_extent` becomes `size() - offset`. Since + // `offset <= size()` from the check above, then `offset` is a valid offset + // for data(), and `offset + new_extent = offset + size() - offset = size() + // >= offset` is also a valid offset that is not before `offset`. This makes + // a span at `offset` with size `new_extent` valid. + // + // Otherwise `count <= size() - offset` and `0 <= offset <= size()` by the + // checks above, so `offset <= size() - count` and `size() - count` can not + // underflow. Then `offset` is a valid offset for data() and `new_extent` is + // `count <= size() - offset`, so `offset + new_extent <= offset + size() - + // offset = size()` which makes both `offset` and `offset + new_extent` + // valid offsets for data(), and since `new_extent` is non-negative, `offset + // + new_extent` is not before `offset` so `new_extent` is a valid size for + // the span at `data() + offset`. + return UNSAFE_BUFFERS({data() + offset, new_extent}); + } + + // Splits a span into two at the given `offset`, returning two spans that + // cover the full range of the original span. + // + // Similar to calling subspan() with the `offset` as the length on the first + // call, and then the `offset` as the offset in the second. + // + // The split_at() overload allows construction of a fixed-size span from a + // compile-time constant. If the input span is fixed-size, both output output + // spans will be. Otherwise, the first will be fixed-size and the second will + // be dynamic-size. + // + // This is a non-std extension that is inspired by the Rust slice::split_at() + // and split_at_mut() methods. + // + // # Checks + // The function CHECKs that the span contains at least `offset` elements and + // will terminate otherwise. + constexpr std::pair, span> split_at(size_t offset) const noexcept { + return {first(offset), subspan(offset)}; + } + + // An overload of `split_at` which returns a fixed-size span. + // + // # Checks + // The function CHECKs that the span contains at least `Offset` elements and + // will terminate otherwise. + template + constexpr std::pair, span> split_at() const noexcept { + CHECK_LE(Offset, size()); + return {first(), subspan(Offset)}; } // [span.obs], span observers @@ -478,30 +845,63 @@ class GSL_POINTER span { [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access + // + // # Checks + // The function CHECKs that the `idx` is inside the span and will terminate + // otherwise. constexpr T& operator[](size_t idx) const noexcept { CHECK_LT(idx, size()); - return data()[idx]; + // SAFETY: Since data() always points to at least `size()` elements, the + // check above ensures `idx < size()` and is thus in range for data(). + return UNSAFE_BUFFERS(data()[idx]); } + // Returns a reference to the first element in the span. + // + // # Checks + // The function CHECKs that the span is not empty and will terminate + // otherwise. constexpr T& front() const noexcept { CHECK(!empty()); - return data()[0]; + // SAFETY: Since data() always points to at least `size()` elements, the + // check above above ensures `0 < size()` and is thus in range for data(). + return UNSAFE_BUFFERS(data()[0]); } + // Returns a reference to the last element in the span. + // + // # Checks + // The function CHECKs that the span is not empty and will terminate + // otherwise. constexpr T& back() const noexcept { CHECK(!empty()); - return data()[size() - 1]; + // SAFETY: Since data() always points to at least `size()` elements, the + // check above above ensures `size() > 0` and thus `size() - 1` does not + // underflow and is in range for data(). + return UNSAFE_BUFFERS(data()[size() - 1]); } + // Returns a pointer to the first element in the span. If the span is empty + // (`size()` is 0), the returned pointer may or may not be null, and it must + // not be dereferenced. + // + // It is always valid to add `size()` to the the pointer in C++ code, though + // it may be invalid in C code when the span is empty. constexpr T* data() const noexcept { return data_; } // [span.iter], span iterator support constexpr iterator begin() const noexcept { - return iterator(data(), data() + size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements, and size() is non-negative. So data() + size() is a valid + // pointer for the data() allocation. + return UNSAFE_BUFFERS(iterator(data(), data() + size())); } constexpr iterator end() const noexcept { - return iterator(data(), data() + size(), data() + size()); + // SAFETY: span provides that data() points to at least `size()` many + // elements, and size() is non-negative. So data() + size() is a valid + // pointer for the data() allocation. + return UNSAFE_BUFFERS(iterator(data(), data() + size(), data() + size())); } constexpr reverse_iterator rbegin() const noexcept { @@ -512,15 +912,44 @@ class GSL_POINTER span { return reverse_iterator(begin()); } - // Bounds-checked copy of spans into spans. The spans must be the exact - // same size or a hard CHECK() occurs. This is a non-std extension that - // is inspired by the Rust slice::copy_from_slice() method. - template - void copy_from(const span& other) - requires(internal::LegalDataConversion) - { + // Bounds-checked copy from a non-overlapping span. The spans must be the + // exact same size or a hard CHECK() occurs. If the two spans overlap, + // Undefined Behaviour occurs. + // + // This is a non-std extension that is inspired by the Rust + // slice::copy_from_slice() method. + // + // # Checks + // The function CHECKs that the `other` span has the same size as itself and + // will terminate otherwise. + constexpr void copy_from(span other) { CHECK_EQ(size_bytes(), other.size_bytes()); - std::ranges::copy(other, data()); + // Verify non-overlapping in developer builds. + // + // SAFETY: span provides that data() points to at least size() many + // elements, so adding size() to the data() pointer is well-defined. + DCHECK(UNSAFE_BUFFERS(data() + size()) <= other.data() || + data() >= UNSAFE_BUFFERS(other.data() + other.size())); + // When compiling with -Oz, std::ranges::copy() does not get inlined, which + // makes copy_from() very expensive compared to memcpy for small sizes (up + // to around 4x slower). We observe that this is because ranges::copy() uses + // begin()/end() and span's iterators are checked iterators, not just + // pointers. This additional complexity prevents inlining and breaks the + // ability for the compiler to eliminate code. + // + // See also https://crbug.com/1396134. + // + // We also see std::copy() (with pointer arguments! not iterators) optimize + // and inline better than memcpy() since memcpy() needs to rely on + // size_bytes(), which while computable at compile time when `other` has a + // fixed size, the optimizer stumbles on with -Oz. + // + // SAFETY: The copy() here does not check bounds, but we have verified that + // `this` and `other` have the same bounds above (and are pointers of the + // same type), so `data()` and `other.data()` both have at least + // `other.size()` elements. + UNSAFE_BUFFERS( + std::copy(other.data(), other.data() + other.size(), data())); } private: @@ -543,19 +972,35 @@ span(R&&) -> span, T, const T>, internal::ExtentV>; +template +span(const T (&)[N]) -> span; + // [span.objectrep], views of object representation template auto as_bytes(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; - return span(reinterpret_cast(s.data()), - s.size_bytes()); + // SAFETY: span provides that data() points to at least size_bytes() many + // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is + // a valid size for a span at data() when viewed as `uint8_t*`. + // + // The reinterpret_cast is valid as the alignment of uint8_t (which is 1) is + // always less-than or equal to the alignment of T. + return UNSAFE_BUFFERS(span( + reinterpret_cast(s.data()), s.size_bytes())); } template requires(!std::is_const_v) auto as_writable_bytes(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; - return span(reinterpret_cast(s.data()), s.size_bytes()); + // SAFETY: span provides that data() points to at least size_bytes() many + // bytes. So since `uint8_t` has a size of 1 byte, the size_bytes() value is a + // valid size for a span at data() when viewed as `uint8_t*`. + // + // The reinterpret_cast is valid as the alignment of uint8_t (which is 1) is + // always less-than or equal to the alignment of T. + return UNSAFE_BUFFERS( + span(reinterpret_cast(s.data()), s.size_bytes())); } // as_chars() is the equivalent of as_bytes(), except that it returns a @@ -565,8 +1010,14 @@ auto as_writable_bytes(span s) noexcept { template auto as_chars(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; - return span(reinterpret_cast(s.data()), - s.size_bytes()); + // SAFETY: span provides that data() points to at least size_bytes() many + // bytes. So since `char` has a size of 1 byte, the size_bytes() value is a + // valid size for a span at data() when viewed as `char*`. + // + // The reinterpret_cast is valid as the alignment of char (which is 1) is + // always less-than or equal to the alignment of T. + return UNSAFE_BUFFERS(span( + reinterpret_cast(s.data()), s.size_bytes())); } // as_writable_chars() is the equivalent of as_writable_bytes(), except that @@ -577,23 +1028,50 @@ template requires(!std::is_const_v) auto as_writable_chars(span s) noexcept { constexpr size_t N = X == dynamic_extent ? dynamic_extent : sizeof(T) * X; - return span(reinterpret_cast(s.data()), s.size_bytes()); + // SAFETY: span provides that data() points to at least size_bytes() many + // bytes. So since `char` has a size of 1 byte, the size_bytes() value is + // a valid size for a span at data() when viewed as `char*`. + // + // The reinterpret_cast is valid as the alignment of char (which is 1) is + // always less-than or equal to the alignment of T. + return UNSAFE_BUFFERS( + span(reinterpret_cast(s.data()), s.size_bytes())); } -// Type-deducing helpers for constructing a span. +// Type-deducing helper for constructing a span. +// +// # Safety +// The contiguous iterator `it` must point to the first element of at least +// `size` many elements or Undefined Behaviour may result as the span may give +// access beyond the bounds of the collection pointed to by `it`. template -constexpr auto make_span(It it, StrictNumeric size) noexcept { +UNSAFE_BUFFER_USAGE constexpr auto make_span( + It it, + StrictNumeric size) noexcept { using T = std::remove_reference_t>; - return span(it, size); + // SAFETY: The caller guarantees that `it` is the first of at least `size` + // many elements. + return UNSAFE_BUFFERS(span(it, size)); } +// Type-deducing helper for constructing a span. +// +// # Checks +// The function CHECKs that `it <= end` and will terminate otherwise. +// +// # Safety +// The contiguous iterator `it` and its end sentinel `end` must be for the same +// allocation or Undefined Behaviour may result as the span may give access +// beyond the bounds of the collection pointed to by `it`. template >> -constexpr auto make_span(It it, End end) noexcept { +UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, End end) noexcept { using T = std::remove_reference_t>; - return span(it, end); + // SAFETY: The caller guarantees that `it` and `end` are iterators of the + // same allocation. + return UNSAFE_BUFFERS(span(it, end)); } // make_span utility function that deduces both the span's value_type and extent @@ -608,44 +1086,142 @@ constexpr auto make_span(Container&& container) noexcept { return span(std::forward(container)); } -// make_span utility functions that allow callers to explicit specify the span's +// make_span utility function that allows callers to explicit specify the span's // extent, the value_type is deduced automatically. This is useful when passing // a dynamically sized container to a method expecting static spans, when the // container is known to have the correct size. // // Note: This will CHECK that N indeed matches size(container). // -// Usage: auto static_span = base::make_span(...); +// # Usage +// As this function is unsafe, the caller must guarantee that the size is +// correct for the iterator, and will not allow the span to reach out of bounds. +// ``` +// // SAFETY: . +// auto static_span = UNSAFE_BUFFERS(base::make_span(it, size)); +// ``` +// +// # Safety +// The contiguous iterator `it` must point to the first element of at least +// `size` many elements or Undefined Behaviour may result as the span may give +// access beyond the bounds of the collection pointed to by `it`. template -constexpr auto make_span(It it, StrictNumeric size) noexcept { +UNSAFE_BUFFER_USAGE constexpr auto make_span( + It it, + StrictNumeric size) noexcept { using T = std::remove_reference_t>; - return span(it, size); + // SAFETY: The caller guarantees that `it` is the first of at least `size` + // many elements. + return UNSAFE_BUFFERS(span(it, size)); } +// make_span utility function that allows callers to explicit specify the span's +// extent, the value_type is deduced automatically. This is useful when passing +// a dynamically sized container to a method expecting static spans, when the +// container is known to have the correct size. +// +// Note: This will CHECK that N indeed matches size(container). +// +// # Usage +// As this function is unsafe, the caller must guarantee that the `end` is from +// the same allocation as the `it` iterator. +// ``` +// // SAFETY: . +// auto static_span = UNSAFE_BUFFERS(base::make_span(it, end)); +// ``` +// +// # Checks +// The function CHECKs that `it <= end` and will terminate otherwise. +// +// # Safety +// The contiguous iterator `it` and its end sentinel `end` must be for the same +// allocation or Undefined Behaviour may result as the span may give access +// beyond the bounds of the collection pointed to by `it`. template >> -constexpr auto make_span(It it, End end) noexcept { +UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, End end) noexcept { using T = std::remove_reference_t>; - return span(it, end); + // SAFETY: The caller guarantees that `it` and `end` are iterators of the + // same allocation. + return UNSAFE_BUFFERS(span(it, end)); } template constexpr auto make_span(Container&& container) noexcept { using T = std::remove_pointer_t()))>; - return span(std::data(container), std::size(container)); + // SAFETY: The std::size() function gives the number of elements pointed to by + // the std::data() function, which meets the requirement of span. + return UNSAFE_BUFFERS(span(std::data(container), std::size(container))); } // `span_from_ref` converts a reference to T into a span of length 1. This is a // non-std helper that is inspired by the `std::slice::from_ref()` function from // Rust. template -static constexpr span span_from_ref( +constexpr span span_from_ref( T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - return span(&single_object, 1u); + // SAFETY: Given a valid reference to `single_object` the span of size 1 will + // be a valid span that points to the `single_object`. + return UNSAFE_BUFFERS(span(std::addressof(single_object), 1u)); +} + +// `byte_span_from_ref` converts a reference to T into a span of uint8_t of +// length sizeof(T). This is a non-std helper that is a sugar for +// `as_writable_bytes(span_from_ref(x))`. +// +// Const references are turned into a `span` while mutable +// references are turned into a `span`. +template +constexpr span byte_span_from_ref( + const T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { + return as_bytes(span_from_ref(single_object)); +} +template +constexpr span byte_span_from_ref( + T& single_object ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { + return as_writable_bytes(span_from_ref(single_object)); +} + +// Converts a string literal (such as `"hello"`) to a span of `char` while +// omitting the terminating NUL character. These two are equivalent: +// ``` +// base::span s1 = base::span_from_cstring("hello"); +// base::span s2 = base::span(std::string_view("hello")); +// ``` +// +// If you want to include the NUL terminator, then use the span constructor +// directly, such as: +// ``` +// base::span s = base::span("hello"); +// ``` +template +constexpr span span_from_cstring( + const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) { + return span(lit).template first(); +} + +// Converts a string literal (such as `"hello"`) to a span of `uint8_t` while +// omitting the terminating NUL character. These two are equivalent: +// ``` +// base::span s1 = base::byte_span_from_cstring("hello"); +// base::span s2 = base::as_byte_span(std::string_view("hello")); +// ``` +// +// If you want to include the NUL terminator, then use the span constructor +// directly, such as: +// ``` +// base::span s = base::as_bytes(base::span("hello")); +// ``` +template +constexpr span byte_span_from_cstring( + const char (&lit ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) { + return as_bytes(span(lit).template first()); } // Convenience function for converting an object which is itself convertible @@ -654,10 +1230,52 @@ static constexpr span span_from_ref( // or vector-like objects holding other scalar types, prior to passing them // into an API that requires byte spans. template -span as_byte_span(const T& arg) { + requires requires(const T& arg) { + requires !std::is_array_v>; + make_span(arg); + } +constexpr span as_byte_span(const T& arg) { return as_bytes(make_span(arg)); } +// This overload for arrays preserves the compile-time size N of the array in +// the span type signature span. +template +constexpr span as_byte_span( + const T (&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) { + return as_bytes(make_span(arr)); +} + +// Convenience function for converting an object which is itself convertible +// to span into a span of mutable bytes (i.e. span of uint8_t). Typically used +// to convert std::string or string-objects holding chars, or std::vector +// or vector-like objects holding other scalar types, prior to passing them +// into an API that requires mutable byte spans. +template + requires requires(T&& arg) { + requires !std::is_array_v>; + make_span(arg); + requires !std::is_const_v; + } +constexpr span as_writable_byte_span(T&& arg) { + return as_writable_bytes(make_span(arg)); +} + +// This overload for arrays preserves the compile-time size N of the array in +// the span type signature span. +template + requires(!std::is_const_v) +constexpr span as_writable_byte_span( + T (&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) { + return as_writable_bytes(make_span(arr)); +} +template + requires(!std::is_const_v) +constexpr span as_writable_byte_span( + T (&&arr ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) { + return as_writable_bytes(make_span(arr)); +} + } // namespace base template @@ -674,8 +1292,8 @@ inline constexpr bool std::ranges::enable_view> = true; // * |std::size| should be preferred for plain arrays. // * In run-time contexts, functions such as |std::array::size| should be // preferred. -#define EXTENT(x) \ - ::base::internal::must_not_be_dynamic_extent() +#define EXTENT(x) \ + ::base::internal::must_not_be_dynamic_extent() #endif // BASE_CONTAINERS_SPAN_H_ diff --git a/naiveproxy/src/base/containers/span_nocompile.nc b/naiveproxy/src/base/containers/span_nocompile.nc index 22761d8021..eaa600204b 100644 --- a/naiveproxy/src/base/containers/span_nocompile.nc +++ b/naiveproxy/src/base/containers/span_nocompile.nc @@ -167,6 +167,18 @@ void NotSizeTSize() { span s2(vector.data(), kSize2); // expected-error@*:* {{The source type is out of range for the destination type}} } +void BadConstConversionsWithStdSpan() { + int kData[] = {10, 11, 12}; + { + base::span fixed_base_span(kData); + std::span s(fixed_base_span); // expected-error {{no matching constructor}} + } + { + std::span fixed_std_span(kData); + base::span s(fixed_std_span); // expected-error {{no matching constructor}} + } +} + void FromVolatileArrayDisallowed() { static volatile int array[] = {1, 2, 3}; span s(array); // expected-error {{no matching constructor for initialization of 'span'}} @@ -175,7 +187,14 @@ void FromVolatileArrayDisallowed() { void FixedSizeCopyTooSmall() { const int src[] = {1, 2, 3}; int dst[2]; - base::make_span(dst).copy_from(base::make_span(src)); // expected-error@*:* {{span size mismatch}} + base::span(dst).copy_from(base::make_span(src)); // expected-error@*:* {{no viable conversion}} + + base::span(dst).copy_from(src); // expected-error@*:* {{no viable conversion}} +} + +void FixedSizeSplitAtOutOfBounds() { + const int arr[] = {1, 2, 3}; + base::span(arr).split_at<4u>(); // expected-error@*:* {{no matching member function for call to 'split_at'}} } void FromRefNoSuchFunctionForIntLiteral() { @@ -199,4 +218,17 @@ void FromRefLifetimeBoundErrorForTemporaryStringObject() { span_from_ref("temporary string"); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} } +void RvalueArrayLifetime() { + [[maybe_unused]] auto wont_work = + as_byte_span({1, 2}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} +} + +void FromCStringThatIsntStaticLifetime() { + [[maybe_unused]] auto wont_work = + span_from_cstring({'a', 'b', '\0'}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work' will be destroyed at the end of the full-expression}} + + [[maybe_unused]] auto wont_work2 = + byte_span_from_cstring({'a', 'b', '\0'}); // expected-error@*:* {{temporary whose address is used as value of local variable 'wont_work2' will be destroyed at the end of the full-expression}} +} + } // namespace base diff --git a/naiveproxy/src/base/critical_closure.h b/naiveproxy/src/base/critical_closure.h index 7e3369ea8a..064d56a0ba 100644 --- a/naiveproxy/src/base/critical_closure.h +++ b/naiveproxy/src/base/critical_closure.h @@ -11,8 +11,9 @@ #include "base/location.h" #include "base/strings/string_piece.h" #include "build/build_config.h" +#include "build/ios_buildflags.h" -#if BUILDFLAG(IS_IOS) +#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION) #include "base/functional/bind.h" #include "base/ios/scoped_critical_action.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -22,7 +23,7 @@ namespace base { namespace internal { -#if BUILDFLAG(IS_IOS) +#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION) // This class wraps a closure so it can continue to run for a period of time // when the application goes to the background by using // |ios::ScopedCriticalAction|. @@ -78,7 +79,7 @@ class PendingCriticalClosure { // // This function is used automatically for tasks posted to a sequence runner // using TaskShutdownBehavior::BLOCK_SHUTDOWN. -#if BUILDFLAG(IS_IOS) +#if BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION) inline OnceClosure MakeCriticalClosure(StringPiece task_name, OnceClosure closure, bool is_immediate) { @@ -104,7 +105,7 @@ inline OnceClosure MakeCriticalClosure(const Location& posted_from, is_immediate); } -#else // BUILDFLAG(IS_IOS) +#else // BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION) inline OnceClosure MakeCriticalClosure(StringPiece task_name, OnceClosure closure, @@ -120,7 +121,7 @@ inline OnceClosure MakeCriticalClosure(const Location& posted_from, return closure; } -#endif // BUILDFLAG(IS_IOS) +#endif // BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_IOS_APP_EXTENSION) } // namespace base diff --git a/naiveproxy/src/base/debug/debugger_posix.cc b/naiveproxy/src/base/debug/debugger_posix.cc index 6ac840b89f..8e499f5964 100644 --- a/naiveproxy/src/base/debug/debugger_posix.cc +++ b/naiveproxy/src/base/debug/debugger_posix.cc @@ -17,7 +17,7 @@ #include #include "base/check_op.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/strings/string_util.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" diff --git a/naiveproxy/src/base/feature_list.cc b/naiveproxy/src/base/feature_list.cc index 085d13f932..8a26a978b2 100644 --- a/naiveproxy/src/base/feature_list.cc +++ b/naiveproxy/src/base/feature_list.cc @@ -53,26 +53,31 @@ class EarlyFeatureAccessTracker { } // Invoked when `feature` is accessed before FeatureList registration. - void AccessedFeature(const Feature& feature) { + void AccessedFeature(const Feature& feature, + bool with_feature_allow_list = false) { AutoLock lock(lock_); - if (fail_instantly_) - Fail(&feature); - else if (!feature_) + if (fail_instantly_) { + Fail(&feature, with_feature_allow_list); + } else if (!feature_) { feature_ = &feature; + feature_had_feature_allow_list_ = with_feature_allow_list; + } } // Asserts that no feature was accessed before FeatureList registration. void AssertNoAccess() { AutoLock lock(lock_); - if (feature_) - Fail(feature_); + if (feature_) { + Fail(feature_, feature_had_feature_allow_list_); + } } // Makes calls to AccessedFeature() fail instantly. void FailOnFeatureAccessWithoutFeatureList() { AutoLock lock(lock_); - if (feature_) - Fail(feature_); + if (feature_) { + Fail(feature_, feature_had_feature_allow_list_); + } fail_instantly_ = true; } @@ -89,7 +94,7 @@ class EarlyFeatureAccessTracker { } private: - void Fail(const Feature* feature) { + void Fail(const Feature* feature, bool with_feature_allow_list) { // TODO(crbug.com/1358639): Enable this check on all platforms. #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) #if !BUILDFLAG(IS_NACL) @@ -97,9 +102,14 @@ class EarlyFeatureAccessTracker { // facilitate crash triage. SCOPED_CRASH_KEY_STRING256("FeatureList", "feature-accessed-too-early", feature->name); + SCOPED_CRASH_KEY_BOOL("FeatureList", "early-access-allow-list", + with_feature_allow_list); #endif // !BUILDFLAG(IS_NACL) CHECK(!feature) << "Accessed feature " << feature->name - << " before FeatureList registration."; + << (with_feature_allow_list + ? " which is not on the allow list passed to " + "SetEarlyAccessInstance()." + : " before FeatureList registration."); #endif // !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) && // !BUILDFLAG(IS_CHROMEOS) } @@ -113,6 +123,7 @@ class EarlyFeatureAccessTracker { // First feature to be accessed before FeatureList registration. raw_ptr feature_ GUARDED_BY(lock_) = nullptr; + bool feature_had_feature_allow_list_ GUARDED_BY(lock_) = false; // Whether AccessedFeature() should fail instantly. bool fail_instantly_ GUARDED_BY(lock_) = false; @@ -445,7 +456,9 @@ void FeatureList::GetCommandLineFeatureOverrides( bool FeatureList::IsEnabled(const Feature& feature) { if (!g_feature_list_instance || !g_feature_list_instance->AllowFeatureAccess(feature)) { - EarlyFeatureAccessTracker::GetInstance()->AccessedFeature(feature); + EarlyFeatureAccessTracker::GetInstance()->AccessedFeature( + feature, g_feature_list_instance && + g_feature_list_instance->IsEarlyAccessInstance()); return feature.default_state == FEATURE_ENABLED_BY_DEFAULT; } return g_feature_list_instance->IsFeatureEnabled(feature); @@ -460,7 +473,9 @@ bool FeatureList::IsValidFeatureOrFieldTrialName(StringPiece name) { absl::optional FeatureList::GetStateIfOverridden(const Feature& feature) { if (!g_feature_list_instance || !g_feature_list_instance->AllowFeatureAccess(feature)) { - EarlyFeatureAccessTracker::GetInstance()->AccessedFeature(feature); + EarlyFeatureAccessTracker::GetInstance()->AccessedFeature( + feature, g_feature_list_instance && + g_feature_list_instance->IsEarlyAccessInstance()); // If there is no feature list, there can be no overrides. return absl::nullopt; } @@ -471,7 +486,9 @@ absl::optional FeatureList::GetStateIfOverridden(const Feature& feature) { FieldTrial* FeatureList::GetFieldTrial(const Feature& feature) { if (!g_feature_list_instance || !g_feature_list_instance->AllowFeatureAccess(feature)) { - EarlyFeatureAccessTracker::GetInstance()->AccessedFeature(feature); + EarlyFeatureAccessTracker::GetInstance()->AccessedFeature( + feature, g_feature_list_instance && + g_feature_list_instance->IsEarlyAccessInstance()); return nullptr; } return g_feature_list_instance->GetAssociatedFieldTrial(feature); diff --git a/naiveproxy/src/base/files/file.h b/naiveproxy/src/base/files/file.h index 878d9db1aa..e33842eb91 100644 --- a/naiveproxy/src/base/files/file.h +++ b/naiveproxy/src/base/files/file.h @@ -253,7 +253,7 @@ class BASE_EXPORT File { int WriteAtCurrentPosNoBestEffort(const char* data, int size); // Returns the current size of this file, or a negative number on failure. - int64_t GetLength(); + int64_t GetLength() const; // Truncates the file to the given length. If |length| is greater than the // current size of the file, the file is extended with zeros. If the file diff --git a/naiveproxy/src/base/files/file_path_watcher_stub.cc b/naiveproxy/src/base/files/file_path_watcher_stub.cc index 29b2f6dec7..a29f53cdc3 100644 --- a/naiveproxy/src/base/files/file_path_watcher_stub.cc +++ b/naiveproxy/src/base/files/file_path_watcher_stub.cc @@ -10,7 +10,8 @@ #include -#include "base/notreached.h" +#include "base/check.h" +#include "base/notimplemented.h" #include "base/task/sequenced_task_runner.h" namespace base { diff --git a/naiveproxy/src/base/files/file_posix.cc b/naiveproxy/src/base/files/file_posix.cc index 0808bb0e3a..eca609ccdd 100644 --- a/naiveproxy/src/base/files/file_posix.cc +++ b/naiveproxy/src/base/files/file_posix.cc @@ -19,6 +19,7 @@ static_assert(sizeof(base::stat_wrapper_t::st_size) >= 8); #include "base/check_op.h" +#include "base/notimplemented.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/posix/eintr_wrapper.h" @@ -366,7 +367,7 @@ int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { HANDLE_EINTR(write(file_.get(), data, static_cast(size)))); } -int64_t File::GetLength() { +int64_t File::GetLength() const { DCHECK(IsValid()); SCOPED_FILE_TRACE("GetLength"); diff --git a/naiveproxy/src/base/files/file_util_fuchsia.cc b/naiveproxy/src/base/files/file_util_fuchsia.cc deleted file mode 100644 index 590df53882..0000000000 --- a/naiveproxy/src/base/files/file_util_fuchsia.cc +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -// Note that Fuchsia is not fully POSIX compliant but it can utilize most -// of the POSIX file code in file_util_posix.cc and only specializes a -// subset of functions in this file. - -#include "base/files/file_util.h" - -namespace base { - -// TODO(crbug.com/1261284): Implement CreateAndOpenFdForTemporaryFileInDir. - -// TODO(crbug.com/1261284): Implement GetTempDir. - -// TODO(crbug.com/1261284): Implement GetHomeDir. - -// TODO(crbug.com/1261284): Implement CreateAndOpenTemporaryFileInDir. - -// TODO(crbug.com/1261284): Implement CreateTemporaryFileInDir. - -// TODO(crbug.com/1261284): Implement FormatTemporaryFileName. - -// TODO(crbug.com/1261284): Implement CreateAndOpenTemporaryStreamInDir. - -// TODO(crbug.com/1261284): Implement CreateTemporaryDirInDir. - -// TODO(crbug.com/1261284): Implement CreateNewTempDirectory. - -} // namespace base diff --git a/naiveproxy/src/base/files/file_util_posix.cc b/naiveproxy/src/base/files/file_util_posix.cc index dcb7696d48..cd75e7d966 100644 --- a/naiveproxy/src/base/files/file_util_posix.cc +++ b/naiveproxy/src/base/files/file_util_posix.cc @@ -1139,7 +1139,7 @@ bool VerifyPathControlledByUser(const FilePath& base, // |base| must be a subpath of |path|, so all components should match. // If these CHECKs fail, look at the test that base is a parent of // path at the top of this function. - DCHECK(ip != path_components.end()); + CHECK(ip != path_components.end(), base::NotFatalUntil::M125); DCHECK(*ip == *ib); } diff --git a/naiveproxy/src/base/files/file_util_win.cc b/naiveproxy/src/base/files/file_util_win.cc index a12c3324ab..59c2ed8b66 100644 --- a/naiveproxy/src/base/files/file_util_win.cc +++ b/naiveproxy/src/base/files/file_util_win.cc @@ -816,11 +816,11 @@ bool NormalizeFilePath(const FilePath& path, FilePath* real_path) { // The expansion of |path| into a full path may make it longer. constexpr int kMaxPathLength = MAX_PATH + 10; wchar_t native_file_path[kMaxPathLength]; - // kMaxPathLength includes space for trailing '\0' so we subtract 1. - // Returned length, used_wchars, does not include trailing '\0'. - // Failure is indicated by returning 0 or >= kMaxPathLength. + // On success, `used_wchars` returns the number of written characters, not + // include the trailing '\0'. Thus, failure is indicated by returning 0 or >= + // kMaxPathLength. DWORD used_wchars = ::GetFinalPathNameByHandle( - file.GetPlatformFile(), native_file_path, kMaxPathLength - 1, + file.GetPlatformFile(), native_file_path, kMaxPathLength, FILE_NAME_NORMALIZED | VOLUME_NAME_NT); if (used_wchars >= kMaxPathLength || used_wchars == 0) diff --git a/naiveproxy/src/base/files/file_win.cc b/naiveproxy/src/base/files/file_win.cc index 71c4a2566a..678a6e0b9e 100644 --- a/naiveproxy/src/base/files/file_win.cc +++ b/naiveproxy/src/base/files/file_win.cc @@ -168,7 +168,7 @@ int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { return WriteAtCurrentPos(data, size); } -int64_t File::GetLength() { +int64_t File::GetLength() const { ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); DCHECK(IsValid()); diff --git a/naiveproxy/src/base/functional/bind_internal.h b/naiveproxy/src/base/functional/bind_internal.h index 453de93302..2c3f4d5be9 100644 --- a/naiveproxy/src/base/functional/bind_internal.h +++ b/naiveproxy/src/base/functional/bind_internal.h @@ -27,6 +27,7 @@ #include "base/memory/weak_ptr.h" #include "base/notreached.h" #include "base/types/always_false.h" +#include "base/types/is_complete.h" #include "base/types/is_instantiation.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/functional/function_ref.h" @@ -522,26 +523,19 @@ template struct ExtractCallableRunTypeImpl; -template -struct ExtractCallableRunTypeImpl { - using Type = R(Args...); -}; +#define BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS(quals) \ + template \ + struct ExtractCallableRunTypeImpl { \ + using Type = R(Args...); \ + } -template -struct ExtractCallableRunTypeImpl { - using Type = R(Args...); -}; +BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS(); +BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS(const); +BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS(noexcept); +BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS(const noexcept); -template -struct ExtractCallableRunTypeImpl { - using Type = R(Args...); -}; - -template -struct ExtractCallableRunTypeImpl { - using Type = R(Args...); -}; +#undef BIND_INTERNAL_EXTRACT_CALLABLE_RUN_TYPE_WITH_QUALS // Evaluated to the RunType of the given callable type; e.g. // `ExtractCallableRunType` -> @@ -550,27 +544,52 @@ template using ExtractCallableRunType = typename ExtractCallableRunTypeImpl::Type; -// `IsCallableObject` is true iff `Functor` has a non-overloaded `operator()`. -// This means it fails on some real callable objects, e.g. with templated or -// overloaded `operator()`s. E.g.: -// static_assert(!IsCallableObject); -// -// struct Foo {}; -// static_assert(!IsCallableObject); +// True when `Functor` has a non-overloaded `operator()()`, e.g.: +// struct S1 { +// int operator()(int); +// }; +// static_assert(HasNonOverloadedCallOp); // // int i = 0; // auto f = [i] {}; -// static_assert(!IsCallableObject); +// static_assert(HasNonOverloadedCallOp); // -// // TODO(crbug.com/1409914): Support. -// struct S { +// struct S2 { // int operator()(int); -// char operator()(char); +// std::string operator()(std::string); // }; -// static_assert(!IsCallableObject); +// static_assert(!HasNonOverloadedCallOp); +// +// static_assert(!HasNonOverloadedCallOp); +// +// struct S3 {}; +// static_assert(!HasNonOverloadedCallOp); // ``` template -concept IsCallableObject = requires { &Functor::operator(); }; +concept HasNonOverloadedCallOp = requires { &Functor::operator(); }; + +template +inline constexpr bool IsObjCArcBlockPointer = false; + +#if __OBJC__ && HAS_FEATURE(objc_arc) +template +inline constexpr bool IsObjCArcBlockPointer = true; +#endif + +// True when `Functor` has an overloaded `operator()()` that can be invoked with +// the provided `BoundArgs`. +template +concept HasOverloadedCallOp = requires { + // The functor must be invocable with the bound args. + requires requires(Functor f, BoundArgs... args) { f(args...); }; + // Now exclude invocables that are not cases of overloaded `operator()()`s: + // * `operator()()` exists, but isn't overloaded + requires !HasNonOverloadedCallOp; + // * Function pointer (doesn't have `operator()()`) + requires !std::is_pointer_v; + // * Block pointer (doesn't have `operator()()`) + requires !IsObjCArcBlockPointer; +}; // `HasRefCountedTypeAsRawPtr` is true when any of the `Args` is a raw pointer // to a `RefCounted` type. @@ -589,10 +608,15 @@ struct ForceVoidReturn { // `FunctorTraits<>` // -// See description at top of file. -template +// See description at top of file. This must be declared here so it can be +// referenced in `DecayedFunctorTraits`. +template struct FunctorTraits; +// Provides functor traits for pre-decayed functor types. +template +struct DecayedFunctorTraits; + // Callable types. // This specialization handles lambdas (captureless and capturing) and functors // with a call operator. Capturing lambdas and stateful functors are explicitly @@ -611,9 +635,9 @@ struct FunctorTraits; // // No non-`static` member variables and no virtual functions. // }; // ``` -template - requires IsCallableObject -struct FunctorTraits { +template + requires HasNonOverloadedCallOp +struct DecayedFunctorTraits { using RunType = ExtractCallableRunType; static constexpr bool is_method = false; static constexpr bool is_nullable = false; @@ -627,9 +651,29 @@ struct FunctorTraits { } }; +template + requires HasOverloadedCallOp +struct DecayedFunctorTraits { + // For an overloaded operator()(), it is not possible to resolve the + // actual declared type. Since it is invocable with the bound args, make up a + // signature based on their types. + using RunType = decltype(std::declval()( + std::declval()...))(std::decay_t...); + static constexpr bool is_method = false; + static constexpr bool is_nullable = false; + static constexpr bool is_callback = false; + static constexpr bool is_stateless = std::is_empty_v; + + template + static ExtractReturnType Invoke(RunFunctor&& functor, + RunArgs&&... args) { + return std::forward(functor)(std::forward(args)...); + } +}; + // Functions. -template -struct FunctorTraits { +template +struct DecayedFunctorTraits { using RunType = R(Args...); static constexpr bool is_method = false; static constexpr bool is_nullable = true; @@ -642,37 +686,32 @@ struct FunctorTraits { } }; -template -struct FunctorTraits : FunctorTraits { -}; +template +struct DecayedFunctorTraits + : DecayedFunctorTraits {}; #if BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_64_BITS) -// `__stdcall` functions. -template -struct FunctorTraits : FunctorTraits {}; +// `__stdcall` and `__fastcall` functions. +#define BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS(conv, quals) \ + template \ + struct DecayedFunctorTraits \ + : DecayedFunctorTraits {} -template -struct FunctorTraits - : FunctorTraits {}; - -// `__fastcall` functions. -template -struct FunctorTraits : FunctorTraits { -}; - -template -struct FunctorTraits - : FunctorTraits {}; +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS(__stdcall, ); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS(__stdcall, noexcept); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS(__fastcall, ); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS(__fastcall, noexcept); +#undef BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONV_AND_QUALS #endif // BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_64_BITS) #if __OBJC__ && HAS_FEATURE(objc_arc) // Objective-C blocks. Blocks can be bound as the compiler will ensure their // lifetimes will be correctly managed. -template -struct FunctorTraits { +template +struct DecayedFunctorTraits { using RunType = R(Args...); static constexpr bool is_method = false; static constexpr bool is_nullable = true; @@ -695,8 +734,11 @@ struct FunctorTraits { #endif // __OBJC__ && HAS_FEATURE(objc_arc) // Methods. -template -struct FunctorTraits { +template +struct DecayedFunctorTraits { using RunType = R(Receiver*, Args...); static constexpr bool is_method = true; static constexpr bool is_nullable = true; @@ -711,59 +753,68 @@ struct FunctorTraits { } }; -template -struct FunctorTraits - : FunctorTraits {}; - -template -struct FunctorTraits - : FunctorTraits { +template +struct DecayedFunctorTraits + : DecayedFunctorTraits { using RunType = R(const Receiver*, Args...); }; -template -struct FunctorTraits - : FunctorTraits {}; +#define BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONST_AND_QUALS(constqual, \ + quals) \ + template \ + struct DecayedFunctorTraits \ + : DecayedFunctorTraits {} + +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONST_AND_QUALS(, noexcept); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONST_AND_QUALS(const, noexcept); + +#undef BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_WITH_CONST_AND_QUALS #if BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_64_BITS) // `__stdcall` methods. -template -struct FunctorTraits - : public FunctorTraits {}; +#define BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS(quals) \ + template \ + struct DecayedFunctorTraits \ + : public DecayedFunctorTraits {} -template -struct FunctorTraits - : public FunctorTraits {}; +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS(); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS(const); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS(noexcept); +BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS(const noexcept); -template -struct FunctorTraits - : public FunctorTraits {}; - -template -struct FunctorTraits - : public FunctorTraits {}; +#undef BIND_INTERNAL_DECAYED_FUNCTOR_TRAITS_STDCALL_WITH_QUALS #endif // BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_64_BITS) // `IgnoreResult`s. -template -struct FunctorTraits> : FunctorTraits { - using RunType = - typename ForceVoidReturn::RunType>::RunType; +template +struct DecayedFunctorTraits, BoundArgs...> + : FunctorTraits { + using RunType = typename ForceVoidReturn< + typename FunctorTraits::RunType>::RunType; template static void Invoke(IgnoreResultType&& ignore_result_helper, RunArgs&&... args) { - FunctorTraits::Invoke( + FunctorTraits::Invoke( std::forward(ignore_result_helper).functor_, std::forward(args)...); } }; // `OnceCallback`s. -template -struct FunctorTraits> { +template +struct DecayedFunctorTraits, BoundArgs...> { using RunType = R(Args...); static constexpr bool is_method = false; static constexpr bool is_nullable = true; @@ -779,8 +830,8 @@ struct FunctorTraits> { }; // `RepeatingCallback`s. -template -struct FunctorTraits> { +template +struct DecayedFunctorTraits, BoundArgs...> { using RunType = R(Args...); static constexpr bool is_method = false; static constexpr bool is_nullable = true; @@ -795,8 +846,16 @@ struct FunctorTraits> { } }; -template -using MakeFunctorTraits = FunctorTraits>; +// For most functors, the traits should not depend on how the functor is passed, +// so decay the functor. +template +// This requirement avoids "implicit instantiation of undefined template" errors +// when the underlying `DecayedFunctorTraits<>` cannot be instantiated. Instead, +// this template will also not be instantiated, and the caller can detect and +// handle that. + requires IsComplete, BoundArgs...>> +struct FunctorTraits + : DecayedFunctorTraits, BoundArgs...> {}; // `StorageTraits<>` // @@ -848,24 +907,30 @@ using ValidateStorageTraits = StorageTraits>; // // Weak calls need special syntax that is applied to the first argument to check // if they should no-op themselves. -template +template struct InvokeHelper; -template -struct InvokeHelper { +template +struct InvokeHelper { template static inline ReturnType MakeItSo(Functor&& functor, BoundArgsTuple&& bound, RunArgs&&... args) { - return MakeFunctorTraits::Invoke( + return Traits::Invoke( std::forward(functor), Unwrap(std::get(std::forward(bound)))..., std::forward(args)...); } }; -template -struct InvokeHelper { +template +struct InvokeHelper { template static inline void MakeItSo(Functor&& functor, BoundArgsTuple&& bound, @@ -878,7 +943,7 @@ struct InvokeHelper { if (!target) { return; } - MakeFunctorTraits::Invoke( + Traits::Invoke( std::forward(functor), target, Unwrap(std::get(std::forward(bound)))..., std::forward(args)...); @@ -888,11 +953,14 @@ struct InvokeHelper { // `Invoker<>` // // See description at the top of the file. -template +template struct Invoker; -template -struct Invoker { +template +struct Invoker { private: using Indices = std::make_index_sequence< std::tuple_size_v>; @@ -975,7 +1043,7 @@ struct Invoker { using DecayedArgsTuple = std::decay_t; static constexpr bool kIsWeakCall = - kIsWeakMethod::is_method, + kIsWeakMethod...>; if constexpr (WeakCallReturnsVoid::value) { // Do not `Unwrap()` here, as that immediately triggers dangling pointer @@ -988,7 +1056,7 @@ struct Invoker { // a memory safety error because protecting raw pointers usage with weak // receivers (where the weak receiver usually own the pointed objects) is // a common and broadly used pattern in the codebase. - return InvokeHelper::MakeItSo( + return InvokeHelper::MakeItSo( std::forward(functor), std::forward(bound), std::forward(unbound_args)...); } @@ -1044,10 +1112,13 @@ void VerifyMethodReceiver(Receiver&& receiver, Unused&&...) { // `BindState<>` // // This stores all the state passed into `Bind()`. -template +template struct BindState final : BindStateBase { private: - using FunctorTraits = MakeFunctorTraits; using BoundArgsTuple = std::tuple; public: @@ -1055,7 +1126,7 @@ struct BindState final : BindStateBase { static BindState* Create(BindStateBase::InvokeFuncStorage invoke_func, ForwardFunctor&& functor, ForwardBoundArgs&&... bound_args) { - if constexpr (FunctorTraits::is_method) { + if constexpr (is_method) { VerifyMethodReceiver(bound_args...); } return new BindState(invoke_func, std::forward(functor), @@ -1121,12 +1192,12 @@ struct BindState final : BindStateBase { } void CheckFunctorIsNonNull() const { - if constexpr (FunctorTraits::is_nullable) { + if constexpr (is_nullable) { // Check the validity of `functor_` to avoid hard-to-diagnose crashes. // Ideally we'd do this unconditionally, but release builds limit this to // the case of nested callbacks (e.g. `Bind(callback, ...)`) to limit // binary size impact. - if constexpr (FunctorTraits::is_callback) { + if constexpr (is_callback) { CHECK(!!functor_); } else { DCHECK(!!functor_); @@ -1138,11 +1209,22 @@ struct BindState final : BindStateBase { // Used to determine and validate the appropriate `BindState`. The // specializations below cover all cases. The members are similar in intent to // those in `StorageTraits`; see comments there. -template +template struct ValidateBindStateType; -template -struct ValidateBindStateType { +template +struct ValidateBindStateType { private: template ...>> struct NoRawPtrsToRefCountedTypes { @@ -1154,21 +1236,33 @@ struct ValidateBindStateType { }; public: - using Type = BindState, + using Type = BindState, typename ValidateStorageTraits::Type...>; static constexpr bool value = std::conjunction_v, ValidateStorageTraits...>; }; -template -struct ValidateBindStateType { - using Type = BindState>; +template +struct ValidateBindStateType { + using Type = BindState>; static constexpr bool value = true; }; -template -struct ValidateBindStateType { +template +struct ValidateBindStateType { private: using DecayedReceiver = std::decay_t; using ReceiverStorageType = @@ -1214,7 +1308,10 @@ struct ValidateBindStateType { }; public: - using Type = BindState, + using Type = BindState, ReceiverStorageType, typename ValidateStorageTraits::Type...>; static constexpr bool value = @@ -1580,6 +1677,17 @@ struct BindHelper { static constexpr bool kIsOnce = is_instantiation>; + template > + struct TraitsAreInstantiable { + static constexpr bool value = [] { + static_assert( + v, "Could not determine how to invoke functor. If this functor has " + "an overloaded operator()(), bind all arguments to it, and ensure " + "the result will select a unique overload."); + return v; + }(); + }; + template > || (kIsOnce && std::is_rvalue_reference_v && @@ -1627,7 +1735,7 @@ struct BindHelper { }(); }; - template ::is_stateless> + template struct IsStateless { static constexpr bool value = [] { static_assert( @@ -1658,7 +1766,7 @@ struct BindHelper { // ``` // And the implementation below is effectively: // ``` - // using FunctorTraits = struct { + // using Traits = struct { // using RunType = double(S*, int, const std::string&); // static constexpr bool is_method = true; // static constexpr bool is_nullable = true; @@ -1685,46 +1793,52 @@ struct BindHelper { // using CallbackType = OnceCallback; // ... // ``` - using FunctorTraits = MakeFunctorTraits; - using ValidatedUnwrappedTypes = - ValidateUnwrappedTypeList; - using BoundArgsList = TypeList; - using RunParamsList = ExtractArgs; - using BoundParamsList = TakeTypeListItem; - using ValidatedBindState = - ValidateBindStateType; - // This conditional checks if each of the `args` matches to the - // corresponding param of the target function. This check does not affect - // the behavior of `Bind()`, but its error message should be more readable. - if constexpr (std::conjunction_v< - NotFunctionRef, IsStateless, - ValidatedUnwrappedTypes, - ParamsCanBeBound< - FunctorTraits::is_method, - std::make_index_sequence, - BoundArgsList, typename ValidatedUnwrappedTypes::Type, - BoundParamsList>, - ValidatedBindState>) { - using UnboundRunType = - MakeFunctionType, - DropTypeListItem>; - using CallbackType = CallbackT; + using Traits = + FunctorTraits...>; + if constexpr (TraitsAreInstantiable::value) { + using ValidatedUnwrappedTypes = + ValidateUnwrappedTypeList; + using BoundArgsList = TypeList; + using RunParamsList = ExtractArgs; + using BoundParamsList = TakeTypeListItem; + using ValidatedBindState = + ValidateBindStateType; + // This conditional checks if each of the `args` matches to the + // corresponding param of the target function. This check does not affect + // the behavior of `Bind()`, but its error message should be more + // readable. + if constexpr (std::conjunction_v< + NotFunctionRef, IsStateless, + ValidatedUnwrappedTypes, + ParamsCanBeBound< + Traits::is_method, + std::make_index_sequence, + BoundArgsList, + typename ValidatedUnwrappedTypes::Type, + BoundParamsList>, + ValidatedBindState>) { + using UnboundRunType = + MakeFunctionType, + DropTypeListItem>; + using CallbackType = CallbackT; - // Store the invoke func into `PolymorphicInvoke` before casting it to - // `InvokeFuncStorage`, so that we can ensure its type matches to - // `PolymorphicInvoke`, to which `CallbackType` will cast back. - typename CallbackType::PolymorphicInvoke invoke_func; - using Invoker = - Invoker; - if constexpr (kIsOnce) { - invoke_func = Invoker::RunOnce; - } else { - invoke_func = Invoker::Run; + // Store the invoke func into `PolymorphicInvoke` before casting it to + // `InvokeFuncStorage`, so that we can ensure its type matches to + // `PolymorphicInvoke`, to which `CallbackType` will cast back. + typename CallbackType::PolymorphicInvoke invoke_func; + using Invoker = + Invoker; + if constexpr (kIsOnce) { + invoke_func = Invoker::RunOnce; + } else { + invoke_func = Invoker::Run; + } + + return CallbackType(ValidatedBindState::Type::Create( + reinterpret_cast(invoke_func), + std::forward(functor), std::forward(args)...)); } - - return CallbackType(ValidatedBindState::Type::Create( - reinterpret_cast(invoke_func), - std::forward(functor), std::forward(args)...)); } } @@ -1856,8 +1970,9 @@ struct CallbackCancellationTraits { // Specialization for a weak receiver. template - requires internal::kIsWeakMethod::is_method, - BoundArgs...> + requires internal::kIsWeakMethod< + internal::FunctorTraits::is_method, + BoundArgs...> struct CallbackCancellationTraits> { static constexpr bool is_cancellable = true; diff --git a/naiveproxy/src/base/functional/bind_nocompile.nc b/naiveproxy/src/base/functional/bind_nocompile.nc index 341f141b30..2c6cc4a891 100644 --- a/naiveproxy/src/base/functional/bind_nocompile.nc +++ b/naiveproxy/src/base/functional/bind_nocompile.nc @@ -7,6 +7,8 @@ #define FORCE_UNRETAINED_COMPLETENESS_CHECKS_FOR_TESTS 1 +#include + #include #include "base/functional/bind.h" @@ -19,7 +21,7 @@ namespace base { void NonConstFunctionWithConstObject() { - struct S : public RefCounted { + struct S : RefCounted { void Method() {} } s; const S* const const_s_ptr = &s; @@ -38,10 +40,10 @@ void WrongReceiverTypeForNonRefcounted() { } a; // Using distinct types causes distinct template instantiations, so we get // assertion failures below where we expect. These types facilitate that. - struct B : public A {} b; - struct C : public A {} c; - struct D : public A {} d; - struct E : public A {}; + struct B : A {} b; + struct C : A {} c; + struct D : A {} d; + struct E : A {}; A* ptr_a = &a; A& ref_a = a; raw_ptr rawptr_a(&a); @@ -84,13 +86,13 @@ void WrongReceiverTypeForNonRefcounted() { void WrongReceiverTypeForRefcounted() { // Refcounted objects must pass a pointer-like `this` argument. - struct A : public RefCounted { + struct A : RefCounted { void Method() const {} } a; // Using distinct types causes distinct template instantiations, so we get // assertion failures below where we expect. These types facilitate that. - struct B : public A {} b; - struct C : public A {}; + struct B : A {} b; + struct C : A {}; const A const_a; B& ref_b = b; const C const_c; @@ -133,7 +135,7 @@ void PassingIncorrectRef() { void ArrayAsReceiver() { // A method should not be bindable with an array of objects. Users could // unintentionally attempt to do this via array->pointer decay. - struct S : public RefCounted { + struct S : RefCounted { void Method() const {} }; S s[2]; @@ -142,7 +144,7 @@ void ArrayAsReceiver() { void RefCountedArgs() { // Refcounted types should not be bound as a raw pointers. - struct S : public RefCounted {}; + struct S : RefCounted {}; S s; const S const_s; S* ptr_s = &s; @@ -254,6 +256,32 @@ void OverloadedFunction() { BindRepeating(&F, 1.0f); // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} } +void OverloadedOperator() { + // It's not possible to bind to a functor with an overloaded `operator()()` + // unless the caller supplies arguments that can invoke a unique overload. + struct A { + int64_t operator()(int, int64_t x) { return x; } + uint64_t operator()(int, uint64_t x) { return x; } + A operator()(double, A a) { return a; } + } a; + // Using distinct types causes distinct template instantiations, so we get + // assertion failures below where we expect. These types facilitate that. + struct B : A {} b; + struct C : A {} c; + struct D : A {} d; + + // Partial function application isn't supported, even if it's sufficient to + // "narrow the field" to a single candidate that _could_ eventually match. + BindOnce(a); // expected-error@*:* {{Could not determine how to invoke functor.}} + BindOnce(b, 1.0); // expected-error@*:* {{Could not determine how to invoke functor.}} + + // The supplied args don't match any candidates. + BindOnce(c, 1, nullptr); // expected-error@*:* {{Could not determine how to invoke functor.}} + + // The supplied args inexactly match multiple candidates. + BindOnce(d, 1, 1); // expected-error@*:* {{Could not determine how to invoke functor.}} +} + // Define a type that disallows `Unretained()` via the internal customization // point, so the next test can use it. struct BlockViaCustomizationPoint {}; @@ -293,7 +321,7 @@ void OtherWaysOfPassingDisallowedTypes() { } a; // Using distinct types causes distinct template instantiations, so we get // assertion failures below where we expect. This type facilitates that. - struct B : public A {} b; + struct B : A {} b; BindOnce(&A::Method, Unretained(&a)); // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}} BindOnce([] (const A&) {}, std::cref(a)); // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}} BindOnce([] (B&) {}, std::ref(b)); // expected-error@*:* {{Argument requires unretained storage, but type does not support `Unretained()`.}} diff --git a/naiveproxy/src/base/functional/callback_internal.h b/naiveproxy/src/base/functional/callback_internal.h index 82c0017b7c..611f8d7fde 100644 --- a/naiveproxy/src/base/functional/callback_internal.h +++ b/naiveproxy/src/base/functional/callback_internal.h @@ -24,7 +24,11 @@ namespace internal { class BindStateBase; -template +template struct BindState; struct BASE_EXPORT BindStateBaseRefCountTraits { @@ -79,7 +83,11 @@ class BASE_EXPORT BindStateBase friend class BindStateHolder; // Allowlist subclasses that access the destructor of BindStateBase. - template + template friend struct BindState; friend struct ::base::FakeBindState; diff --git a/naiveproxy/src/base/functional/function_ref.h b/naiveproxy/src/base/functional/function_ref.h index dc60849dab..edee844a90 100644 --- a/naiveproxy/src/base/functional/function_ref.h +++ b/naiveproxy/src/base/functional/function_ref.h @@ -64,7 +64,7 @@ class FunctionRef; template class FunctionRef { template ::RunType> + typename RunType = internal::FunctorTraits::RunType> static constexpr bool kCompatibleFunctor = std::convertible_to, R> && std::same_as, internal::TypeList>; diff --git a/naiveproxy/src/base/functional/unretained_traits.h b/naiveproxy/src/base/functional/unretained_traits.h index b13cd36740..116a74f09a 100644 --- a/naiveproxy/src/base/functional/unretained_traits.h +++ b/naiveproxy/src/base/functional/unretained_traits.h @@ -5,11 +5,12 @@ #ifndef BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_ #define BASE_FUNCTIONAL_UNRETAINED_TRAITS_H_ -#include "build/build_config.h" - #include #include +#include "base/types/is_complete.h" +#include "build/build_config.h" + // Various opaque system types that should still be usable with the base // callback system. Please keep sorted. #define BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED \ @@ -41,13 +42,6 @@ BASE_INTERNAL_LIST_OF_SAFE_FOR_UNRETAINED namespace base::internal { -// True if `T` is completely defined. -template -concept IsComplete = requires { sizeof(T); } || - // Function types must be included explicitly since you - // cannot apply `sizeof()` to a function type. - std::is_function_v>; - template concept SameAsAny = (std::same_as || ...); diff --git a/naiveproxy/src/base/hash/hash.h b/naiveproxy/src/base/hash/hash.h index 05ac9a30ef..d15cd0fbd9 100644 --- a/naiveproxy/src/base/hash/hash.h +++ b/naiveproxy/src/base/hash/hash.h @@ -15,7 +15,6 @@ #include "base/base_export.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" namespace base { @@ -35,7 +34,7 @@ BASE_EXPORT uint32_t Hash(const std::string& str); // publicly available. // May changed without warning, do not expect stability of outputs. BASE_EXPORT size_t FastHash(base::span data); -inline size_t FastHash(StringPiece str) { +inline size_t FastHash(std::string_view str) { return FastHash(as_bytes(make_span(str))); } @@ -46,7 +45,6 @@ inline size_t FastHash(StringPiece str) { // // WARNING: This hash function should not be used for any cryptographic purpose. BASE_EXPORT uint32_t PersistentHash(base::span data); -BASE_EXPORT uint32_t PersistentHash(const void* data, size_t length); BASE_EXPORT uint32_t PersistentHash(std::string_view str); // Hash pairs of 32-bit or 64-bit numbers. diff --git a/naiveproxy/src/base/hash/md5.h b/naiveproxy/src/base/hash/md5.h index aa889f350e..b49701893a 100644 --- a/naiveproxy/src/base/hash/md5.h +++ b/naiveproxy/src/base/hash/md5.h @@ -6,9 +6,10 @@ #define BASE_HASH_MD5_H_ #include +#include #include "base/base_export.h" -#include "base/strings/string_piece.h" +#include "base/containers/span.h" #include "build/build_config.h" #if BUILDFLAG(IS_NACL) @@ -46,10 +47,10 @@ namespace base { // MD5Update(). BASE_EXPORT void MD5Init(MD5Context* context); -// For the given buffer of |data| as a StringPiece, updates the given MD5 +// For the given buffer of |data| as a std::string_view, updates the given MD5 // context with the sum of the data. You can call this any number of times // during the computation, except that MD5Init() must have been called first. -BASE_EXPORT void MD5Update(MD5Context* context, const StringPiece& data); +BASE_EXPORT void MD5Update(MD5Context* context, std::string_view data); // Finalizes the MD5 operation and fills the buffer with the digest. BASE_EXPORT void MD5Final(MD5Digest* digest, MD5Context* context); @@ -57,12 +58,12 @@ BASE_EXPORT void MD5Final(MD5Digest* digest, MD5Context* context); // Converts a digest into human-readable hexadecimal. BASE_EXPORT std::string MD5DigestToBase16(const MD5Digest& digest); -// Computes the MD5 sum of the given data buffer with the given length. -// The given 'digest' structure will be filled with the result data. -BASE_EXPORT void MD5Sum(const void* data, size_t length, MD5Digest* digest); +// Computes the MD5 sum of the given `data`. +// The 'digest' structure will be filled with the result. +BASE_EXPORT void MD5Sum(base::span data, MD5Digest* digest); // Returns the MD5 (in hexadecimal) of a string. -BASE_EXPORT std::string MD5String(const StringPiece& str); +BASE_EXPORT std::string MD5String(std::string_view str); } // namespace base diff --git a/naiveproxy/src/base/hash/md5_boringssl.cc b/naiveproxy/src/base/hash/md5_boringssl.cc index 7e9c93b3c1..88d12fd687 100644 --- a/naiveproxy/src/base/hash/md5_boringssl.cc +++ b/naiveproxy/src/base/hash/md5_boringssl.cc @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/hash/md5.h" +#include +#include "base/hash/md5.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -12,7 +13,7 @@ void MD5Init(MD5Context* context) { MD5_Init(context); } -void MD5Update(MD5Context* context, const StringPiece& data) { +void MD5Update(MD5Context* context, std::string_view data) { MD5_Update(context, reinterpret_cast(data.data()), data.size()); } @@ -25,13 +26,13 @@ std::string MD5DigestToBase16(const MD5Digest& digest) { return ToLowerASCII(HexEncode(digest.a, MD5_DIGEST_LENGTH)); } -void MD5Sum(const void* data, size_t length, MD5Digest* digest) { - MD5(reinterpret_cast(data), length, digest->a); +void MD5Sum(base::span data, MD5Digest* digest) { + MD5(data.data(), data.size(), digest->a); } -std::string MD5String(const StringPiece& str) { +std::string MD5String(std::string_view str) { MD5Digest digest; - MD5Sum(str.data(), str.size(), &digest); + MD5Sum(base::as_byte_span(str), &digest); return MD5DigestToBase16(digest); } } // namespace base diff --git a/naiveproxy/src/base/hash/md5_nacl.cc b/naiveproxy/src/base/hash/md5_nacl.cc index c49e20c660..1af70ae9b3 100644 --- a/naiveproxy/src/base/hash/md5_nacl.cc +++ b/naiveproxy/src/base/hash/md5_nacl.cc @@ -23,6 +23,9 @@ #include +#include + +#include "base/containers/span.h" #include "base/hash/md5.h" #include "base/strings/string_number_conversions.h" @@ -169,7 +172,7 @@ void MD5Init(MD5Context* context) { * Update context to reflect the concatenation of another buffer full * of bytes. */ -void MD5Update(MD5Context* context, const StringPiece& data) { +void MD5Update(MD5Context* context, std::string_view data) { struct Context* ctx = reinterpret_cast(context); const uint8_t* buf = reinterpret_cast(data.data()); size_t len = data.size(); @@ -271,16 +274,17 @@ std::string MD5DigestToBase16(const MD5Digest& digest) { return ret; } -void MD5Sum(const void* data, size_t length, MD5Digest* digest) { +void MD5Sum(span data, MD5Digest* digest) { MD5Context ctx; MD5Init(&ctx); - MD5Update(&ctx, StringPiece(reinterpret_cast(data), length)); + span chars = as_chars(data); + MD5Update(&ctx, std::string_view(chars.data(), chars.size())); MD5Final(digest, &ctx); } -std::string MD5String(const StringPiece& str) { +std::string MD5String(std::string_view str) { MD5Digest digest; - MD5Sum(str.data(), str.length(), &digest); + MD5Sum(as_byte_span(str), &digest); return MD5DigestToBase16(digest); } diff --git a/naiveproxy/src/base/hash/sha1.h b/naiveproxy/src/base/hash/sha1.h index 29626e5853..1891e95fa3 100644 --- a/naiveproxy/src/base/hash/sha1.h +++ b/naiveproxy/src/base/hash/sha1.h @@ -9,10 +9,10 @@ #include #include +#include #include "base/base_export.h" #include "base/containers/span.h" -#include "base/strings/string_piece.h" #include "build/build_config.h" #if BUILDFLAG(IS_NACL) #include "base/hash/sha1_nacl.h" @@ -32,7 +32,7 @@ using SHA1Digest = std::array; BASE_EXPORT SHA1Digest SHA1HashSpan(span data); // Computes the SHA-1 hash of the input string |str| and returns the full // hash. -BASE_EXPORT std::string SHA1HashString(StringPiece str); +BASE_EXPORT std::string SHA1HashString(std::string_view str); // Computes the SHA-1 hash of the |len| bytes in |data| and puts the hash // in |hash|. |hash| must be kSHA1Length bytes long. BASE_EXPORT void SHA1HashBytes(const unsigned char* data, @@ -41,7 +41,7 @@ BASE_EXPORT void SHA1HashBytes(const unsigned char* data, // These functions allow streaming SHA-1 operations. BASE_EXPORT void SHA1Init(SHA1Context& context); -BASE_EXPORT void SHA1Update(const StringPiece data, SHA1Context& context); +BASE_EXPORT void SHA1Update(const std::string_view data, SHA1Context& context); BASE_EXPORT void SHA1Final(SHA1Context& context, SHA1Digest& digest); } // namespace base diff --git a/naiveproxy/src/base/hash/sha1_boringssl.cc b/naiveproxy/src/base/hash/sha1_boringssl.cc index 381165f0be..7d20c1c68b 100644 --- a/naiveproxy/src/base/hash/sha1_boringssl.cc +++ b/naiveproxy/src/base/hash/sha1_boringssl.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/hash/sha1.h" - #include -#include "base/strings/string_util.h" +#include + +#include "base/hash/sha1.h" #include "third_party/boringssl/src/include/openssl/crypto.h" #include "third_party/boringssl/src/include/openssl/sha.h" @@ -21,11 +21,11 @@ SHA1Digest SHA1HashSpan(span data) { return digest; } -std::string SHA1HashString(StringPiece str) { +std::string SHA1HashString(std::string_view str) { CRYPTO_library_init(); - std::string digest; + std::string digest(kSHA1Length, '\0'); SHA1(reinterpret_cast(str.data()), str.size(), - reinterpret_cast(WriteInto(&digest, kSHA1Length + 1))); + reinterpret_cast(digest.data())); return digest; } @@ -39,7 +39,7 @@ void SHA1Init(SHA1Context& context) { SHA1_Init(&context); } -void SHA1Update(const StringPiece data, SHA1Context& context) { +void SHA1Update(const std::string_view data, SHA1Context& context) { SHA1_Update(&context, data.data(), data.size()); } diff --git a/naiveproxy/src/base/hash/sha1_nacl.cc b/naiveproxy/src/base/hash/sha1_nacl.cc index 2b38fdb37a..4e9f0d509c 100644 --- a/naiveproxy/src/base/hash/sha1_nacl.cc +++ b/naiveproxy/src/base/hash/sha1_nacl.cc @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/hash/sha1.h" - #include #include #include +#include + +#include "base/hash/sha1.h" #include "base/sys_byteorder.h" namespace base { @@ -167,7 +168,7 @@ void SHA1Init(SHA1Context& context) { context.Init(); } -void SHA1Update(const StringPiece data, SHA1Context& context) { +void SHA1Update(const std::string_view data, SHA1Context& context) { context.Update(data.data(), data.size()); } @@ -182,7 +183,7 @@ SHA1Digest SHA1HashSpan(span data) { return hash; } -std::string SHA1HashString(StringPiece str) { +std::string SHA1HashString(std::string_view str) { char hash[kSHA1Length]; SHA1HashBytes(reinterpret_cast(str.data()), str.length(), reinterpret_cast(hash)); diff --git a/naiveproxy/src/base/i18n/icu_util.cc b/naiveproxy/src/base/i18n/icu_util.cc index b62e461bb7..2122c479b2 100644 --- a/naiveproxy/src/base/i18n/icu_util.cc +++ b/naiveproxy/src/base/i18n/icu_util.cc @@ -27,6 +27,7 @@ #include "base/strings/string_util.h" #include "build/chromecast_buildflags.h" #include "third_party/icu/source/common/unicode/putil.h" +#include "third_party/icu/source/common/unicode/uclean.h" #include "third_party/icu/source/common/unicode/udata.h" #include "third_party/icu/source/common/unicode/utrace.h" @@ -97,21 +98,18 @@ const char kIcuDataFileName[] = "icudtl.dat"; // See for details: http://userguide.icu-project.org/datetime/timezone const char kIcuTimeZoneEnvVariable[] = "ICU_TIMEZONE_FILES_DIR"; -// Up-to-date time zone data is expected to be provided by the system as a +// Up-to-date time zone data MUST be provided by the system as a // directory offered to Chromium components at /config/tzdata. Chromium -// components should "use" the `tzdata` directory capability, specifying the -// "/config/tzdata" path. The capability's "availability" should be set to -// "required" or "optional" as appropriate - if no data is provided then ICU -// initialization will (in future silently) fall-back to the (potentially stale) -// timezone data included in the package. +// components "use" the `tzdata` directory capability, specifying the +// "/config/tzdata" path. Chromium components will crash if this capability +// is not available. // // TimeZoneDataTest.* tests verify that external timezone data is correctly // loaded from the system, to alert developers if the platform and Chromium // versions are no longer compatible versions. +// LINT.IfChange(icu_time_zone_data_path) const char kIcuTimeZoneDataDir[] = "/config/tzdata/icu/44/le"; - -// Path used to receive tzdata via the legacy config-data mechanism. -const char kLegacyIcuTimeZoneDataDir[] = "/config/data/tzdata/icu/44/le"; +// LINT.ThenChange(//sandbox/policy.fuchsia/sandbox_policy_fuchsia.cc:icu_time_zone_data_path) #endif // BUILDFLAG(IS_FUCHSIA) #if BUILDFLAG(IS_ANDROID) @@ -207,26 +205,11 @@ void InitializeExternalTimeZoneData() { // Set the environment variable to override the location used by ICU. // Loading can still fail if the directory is empty or its data is invalid. std::unique_ptr env = base::Environment::Create(); - - // If the ICU tzdata path exists then do not fall-back to config-data. - // TODO(crbug.com/1360077): Remove fall-back once all components are migrated. - if (base::PathExists(base::FilePath(g_icu_time_zone_data_dir))) { - // If the tzdata directory does not exist then silently fallback to - // using the inbuilt (possibly stale) timezone data. - if (base::DirectoryExists(base::FilePath(g_icu_time_zone_data_dir))) { - env->SetVar(kIcuTimeZoneEnvVariable, g_icu_time_zone_data_dir); - } - - } else if (g_icu_time_zone_data_dir == kIcuTimeZoneDataDir && - base::DirectoryExists( - base::FilePath((kLegacyIcuTimeZoneDataDir)))) { - // Only fall-back to attempting to load from the legacy config-data path - // if `g_icu_time_zone_data_dir` has not been changed by a test. - env->SetVar(kIcuTimeZoneEnvVariable, kLegacyIcuTimeZoneDataDir); - } else { - PLOG(WARNING) << "Could not locate tzdata in config-data. " - << "Using built-in timezone database"; + if (!base::DirectoryExists(base::FilePath(g_icu_time_zone_data_dir))) { + PLOG(FATAL) << "Could not open directory: '" << g_icu_time_zone_data_dir + << "'"; } + env->SetVar(kIcuTimeZoneEnvVariable, g_icu_time_zone_data_dir); #endif // BUILDFLAG(IS_FUCHSIA) } @@ -407,8 +390,15 @@ PlatformFile GetIcuDataFileHandle(MemoryMappedFile::Region* out_region) { } void ResetGlobalsForTesting() { + // Reset ICU library internal state before tearing-down the mapped data + // file, or handle. + u_cleanup(); + + // `g_icudtl_pf` does not actually own the FD once ICU is initialized, so + // don't try to close it here. g_icudtl_pf = kInvalidPlatformFile; - g_icudtl_mapped_file = nullptr; + delete std::exchange(g_icudtl_mapped_file, nullptr); + #if BUILDFLAG(IS_FUCHSIA) g_icu_time_zone_data_dir = kIcuTimeZoneDataDir; #endif // BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/base/i18n/icu_util.h b/naiveproxy/src/base/i18n/icu_util.h index 8069072a24..f50a68de9f 100644 --- a/naiveproxy/src/base/i18n/icu_util.h +++ b/naiveproxy/src/base/i18n/icu_util.h @@ -49,6 +49,8 @@ BASE_I18N_EXPORT bool InitializeICUWithFileDescriptor( PlatformFile data_fd, const MemoryMappedFile::Region& data_region); +// Calls `u_cleanup()` to reset the ICU library, and clears global state, +// notably releasing the mapped ICU data file, and handle. BASE_I18N_EXPORT void ResetGlobalsForTesting(); #if BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/base/ios/ios_util.h b/naiveproxy/src/base/ios/ios_util.h index d847d29251..7a361a176c 100644 --- a/naiveproxy/src/base/ios/ios_util.h +++ b/naiveproxy/src/base/ios/ios_util.h @@ -9,26 +9,11 @@ #include "base/base_export.h" #include "base/files/file_path.h" +#include "build/ios_buildflags.h" namespace base { namespace ios { -// Returns whether the operating system is iOS 12 or later. -// TODO(crbug.com/1129482): Remove once minimum supported version is at least 12 -BASE_EXPORT bool IsRunningOnIOS12OrLater(); - -// Returns whether the operating system is iOS 13 or later. -// TODO(crbug.com/1129483): Remove once minimum supported version is at least 13 -BASE_EXPORT bool IsRunningOnIOS13OrLater(); - -// Returns whether the operating system is iOS 14 or later. -// TODO(crbug.com/1129484): Remove once minimum supported version is at least 14 -BASE_EXPORT bool IsRunningOnIOS14OrLater(); - -// Returns whether the operating system is iOS 15 or later. -// TODO(crbug.com/1227419): Remove once minimum supported version is at least 15 -BASE_EXPORT bool IsRunningOnIOS15OrLater(); - // Returns whether the operating system is iOS 16 or later. BASE_EXPORT bool IsRunningOnIOS16OrLater(); @@ -55,10 +40,12 @@ BASE_EXPORT void OverridePathOfEmbeddedICU(const char* path); // returns invalid FilePath. BASE_EXPORT FilePath FilePathOfEmbeddedICU(); +#if !BUILDFLAG(IS_IOS_APP_EXTENSION) // Returns true iff multiple windows can be opened, i.e. when the multiwindow // build flag is on, the device is running on iOS 13+ and it's a compatible // iPad. BASE_EXPORT bool IsMultipleScenesSupported(); +#endif // iOS 15 introduced pre-warming, which launches and then pauses the app, to // speed up actual launch time. diff --git a/naiveproxy/src/base/ios/ios_util.mm b/naiveproxy/src/base/ios/ios_util.mm index 6ada7304e2..4186d1a23b 100644 --- a/naiveproxy/src/base/ios/ios_util.mm +++ b/naiveproxy/src/base/ios/ios_util.mm @@ -20,26 +20,6 @@ std::string* g_icudtl_path_override = nullptr; namespace base::ios { -bool IsRunningOnIOS12OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(12, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS13OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(13, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS14OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(14, 0, 0); - return is_running_on_or_later; -} - -bool IsRunningOnIOS15OrLater() { - static const bool is_running_on_or_later = IsRunningOnOrLater(15, 0, 0); - return is_running_on_or_later; -} - bool IsRunningOnIOS16OrLater() { static const bool is_running_on_or_later = IsRunningOnOrLater(16, 0, 0); return is_running_on_or_later; @@ -91,12 +71,14 @@ FilePath FilePathOfEmbeddedICU() { return FilePath(); } +#if !BUILDFLAG(IS_IOS_APP_EXTENSION) bool IsMultipleScenesSupported() { if (@available(iOS 13, *)) { return UIApplication.sharedApplication.supportsMultipleScenes; } return false; } +#endif bool IsApplicationPreWarmed() { return [NSProcessInfo.processInfo.environment objectForKey:@"ActivePrewarm"]; diff --git a/naiveproxy/src/base/mac/mac_util.mm b/naiveproxy/src/base/mac/mac_util.mm index 0a2d695509..e9e4b1a908 100644 --- a/naiveproxy/src/base/mac/mac_util.mm +++ b/naiveproxy/src/base/mac/mac_util.mm @@ -31,7 +31,7 @@ #include "base/mac/scoped_ioobject.h" #include "base/posix/sysctl.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" + #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/strings/sys_string_conversions.h" diff --git a/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc b/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc index 88bc538a69..858251b502 100644 --- a/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc +++ b/naiveproxy/src/base/memory/platform_shared_memory_mapper_android.cc @@ -28,7 +28,7 @@ absl::optional> PlatformSharedMemoryMapper::Map( return absl::nullopt; } - return make_span(reinterpret_cast(address), size); + return make_span(static_cast(address), size); } void PlatformSharedMemoryMapper::Unmap(span mapping) { diff --git a/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc b/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc index 19725e0182..04aca9df2b 100644 --- a/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc +++ b/naiveproxy/src/base/memory/platform_shared_memory_mapper_posix.cc @@ -25,7 +25,7 @@ absl::optional> PlatformSharedMemoryMapper::Map( return absl::nullopt; } - return make_span(reinterpret_cast(address), size); + return make_span(static_cast(address), size); } void PlatformSharedMemoryMapper::Unmap(span mapping) { diff --git a/naiveproxy/src/base/memory/platform_shared_memory_mapper_win.cc b/naiveproxy/src/base/memory/platform_shared_memory_mapper_win.cc index 12c75b387d..c277bcc4ed 100644 --- a/naiveproxy/src/base/memory/platform_shared_memory_mapper_win.cc +++ b/naiveproxy/src/base/memory/platform_shared_memory_mapper_win.cc @@ -44,7 +44,7 @@ absl::optional> PlatformSharedMemoryMapper::Map( return absl::nullopt; } - return make_span(reinterpret_cast(address), + return make_span(static_cast(address), GetMemorySectionSize(address)); } diff --git a/naiveproxy/src/base/memory/protected_memory.h b/naiveproxy/src/base/memory/protected_memory.h new file mode 100644 index 0000000000..001153cc3b --- /dev/null +++ b/naiveproxy/src/base/memory/protected_memory.h @@ -0,0 +1,262 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Protected memory is memory holding security-sensitive data intended to be +// left read-only for the majority of its lifetime to avoid being overwritten +// by attackers. ProtectedMemory is a simple wrapper around platform-specific +// APIs to set memory read-write and read-only when required. Protected memory +// should be set read-write for the minimum amount of time required. +// +// Normally mutable variables are held in read-write memory and constant data +// is held in read-only memory to ensure it is not accidentally overwritten. +// In some cases we want to hold mutable variables in read-only memory, except +// when they are being written to, to ensure that they are not tampered with. +// +// ProtectedMemory is a container class intended to hold a single variable in +// read-only memory, except when explicitly set read-write. The variable can be +// set read-write by creating a scoped AutoWritableMemory object by calling +// AutoWritableMemory::Create(), the memory stays writable until the returned +// object goes out of scope and is destructed. The wrapped variable can be +// accessed using operator* and operator->. +// +// Instances of ProtectedMemory must be declared in the PROTECTED_MEMORY_SECTION +// and as global variables. Because protected memory variables are globals, the +// the same rules apply disallowing non-trivial constructors and destructors. +// Global definitions are required to avoid the linker placing statics in +// inlinable functions into a comdat section and setting the protected memory +// section read-write when they are merged. +// +// EXAMPLE: +// +// struct Items { void* item1; }; +// static PROTECTED_MEMORY_SECTION base::ProtectedMemory items; +// void InitializeItems() { +// // Explicitly set items read-write before writing to it. +// auto writer = base::AutoWritableMemory::Create(items); +// items->item1 = /* ... */; +// assert(items->item1 != nullptr); +// // items is set back to read-only on the destruction of writer +// } +// +// using FnPtr = void (*)(void); +// PROTECTED_MEMORY_SECTION base::ProtectedMemory fnPtr; +// FnPtr ResolveFnPtr(void) { +// // The Initializer nested class is a helper class for creating a static +// // initializer for a ProtectedMemory variable. It implicitly sets the +// // variable read-write during initialization. +// static base::ProtectedMemory::Initializer I(&fnPtr, +// reinterpret_cast(dlsym(/* ... */))); +// return *fnPtr; +// } + +#ifndef BASE_MEMORY_PROTECTED_MEMORY_H_ +#define BASE_MEMORY_PROTECTED_MEMORY_H_ + +#include "base/check_op.h" +#include "base/logging.h" +#include "base/memory/protected_memory_buildflags.h" +#include "base/memory/raw_ref.h" +#include "base/no_destructor.h" +#include "base/synchronization/lock.h" +#include "build/build_config.h" + +#if BUILDFLAG(PROTECTED_MEMORY_ENABLED) +#if BUILDFLAG(IS_WIN) +// Define a read-write prot section. The $a, $mem, and $z 'sub-sections' are +// merged alphabetically so $a and $z are used to define the start and end of +// the protected memory section, and $mem holds protected variables. +// (Note: Sections in Portable Executables are equivalent to segments in other +// executable formats, so this section is mapped into its own pages.) +#pragma section("prot$a", read, write) +#pragma section("prot$mem", read, write) +#pragma section("prot$z", read, write) + +// We want the protected memory section to be read-only, not read-write so we +// instruct the linker to set the section read-only at link time. We do this +// at link time instead of compile time, because defining the prot section +// read-only would cause mis-compiles due to optimizations assuming that the +// section contents are constant. +#pragma comment(linker, "/SECTION:prot,R") + +__declspec(allocate("prot$a")) +__declspec(selectany) char __start_protected_memory; +__declspec(allocate("prot$z")) +__declspec(selectany) char __stop_protected_memory; + +#define PROTECTED_MEMORY_SECTION __declspec(allocate("prot$mem")) +#else +#error "Protected Memory is currently only supported on Windows." +#endif // BUILDFLAG(IS_WIN) + +#else +#define PROTECTED_MEMORY_SECTION +#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED) + +namespace base { + +template +class AutoWritableMemory; + +template +class ProtectedMemory { + public: + ProtectedMemory() = default; + ProtectedMemory(const ProtectedMemory&) = delete; + ProtectedMemory& operator=(const ProtectedMemory&) = delete; + + // Expose direct access to the encapsulated variable + const T& operator*() const { return data; } + const T* operator->() const { return &data; } + + // Helper class for creating simple ProtectedMemory static initializers. + class Initializer { + public: + // Defined out-of-line below to break circular definition dependency between + // ProtectedMemory and AutoWritableMemory. + Initializer(ProtectedMemory* PM, T&& Init); + + Initializer() = delete; + Initializer(const Initializer&) = delete; + Initializer& operator=(const Initializer&) = delete; + }; + + private: + friend class AutoWritableMemory; + T data; +}; + +namespace internal { +#if BUILDFLAG(PROTECTED_MEMORY_ENABLED) +// CHECK that the byte at |ptr| is read-only. +BASE_EXPORT void AssertMemoryIsReadOnly(const void* ptr); + +// Abstract out platform-specific memory APIs. |end| points to the byte past +// the end of the region of memory having its memory protections changed. +BASE_EXPORT bool SetMemoryReadWrite(void* start, void* end); +BASE_EXPORT bool SetMemoryReadOnly(void* start, void* end); + +// Abstract out platform-specific methods to get the beginning and end of the +// PROTECTED_MEMORY_SECTION. ProtectedMemoryEnd returns a pointer to the byte +// past the end of the PROTECTED_MEMORY_SECTION. +inline constexpr void* ProtectedMemoryStart = &__start_protected_memory; +inline constexpr void* ProtectedMemoryEnd = &__stop_protected_memory; +#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED) + +#if defined(COMPONENT_BUILD) +// For component builds we want to define a separate global writers variable +// (explained below) in every dynamic shared object (DSO) that includes this +// header. To do that we use this template to define a global without duplicate +// symbol errors. +template +struct DsoSpecific { + static T value; +}; +template +T DsoSpecific::value = 0; +#endif // defined(COMPONENT_BUILD) +} // namespace internal + +// A class that sets a given ProtectedMemory variable writable while the +// AutoWritableMemory is in scope. This class implements the logic for setting +// the protected memory region read-only/read-write in a thread-safe manner. +template +class AutoWritableMemory { + public: + // If this is the first writer (e.g. writers == 0) set the writers variable + // read-write. Next, increment writers and set the requested memory writable. + explicit AutoWritableMemory(ProtectedMemory& protected_memory) + : protected_memory_(protected_memory) { +#if BUILDFLAG(PROTECTED_MEMORY_ENABLED) + T* ptr = &(protected_memory.data); + T* ptr_end = ptr + 1; + CHECK(ptr >= internal::ProtectedMemoryStart && + ptr_end <= internal::ProtectedMemoryEnd); + + { + base::AutoLock auto_lock(writers_lock()); + if (writers == 0) { + internal::AssertMemoryIsReadOnly(ptr); +#if !defined(COMPONENT_BUILD) + internal::AssertMemoryIsReadOnly(&writers); + CHECK(internal::SetMemoryReadWrite(&writers, &writers + 1)); +#endif // !defined(COMPONENT_BUILD) + } + + writers++; + } + + CHECK(internal::SetMemoryReadWrite(ptr, ptr_end)); +#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED) + } + + // On destruction decrement writers, and if no other writers exist, set the + // entire protected memory region read-only. + ~AutoWritableMemory() { +#if BUILDFLAG(PROTECTED_MEMORY_ENABLED) + base::AutoLock auto_lock(writers_lock()); + CHECK_GT(writers, 0); + writers--; + + if (writers == 0) { + CHECK(internal::SetMemoryReadOnly(internal::ProtectedMemoryStart, + internal::ProtectedMemoryEnd)); +#if !defined(COMPONENT_BUILD) + internal::AssertMemoryIsReadOnly(&writers); +#endif // !defined(COMPONENT_BUILD) + } +#endif // BUILDFLAG(PROTECTED_MEMORY_ENABLED) + } + + AutoWritableMemory(AutoWritableMemory& original) = delete; + AutoWritableMemory& operator=(AutoWritableMemory& original) = delete; + AutoWritableMemory(AutoWritableMemory&& original) = delete; + AutoWritableMemory& operator=(AutoWritableMemory&& original) = delete; + + T& GetProtectedData() { return protected_memory_->data; } + T* GetProtectedDataPtr() { return &(protected_memory_->data); } + + private: + // 'writers' is a global holding the number of ProtectedMemory instances set + // writable, used to avoid races setting protected memory readable/writable. + // When this reaches zero the protected memory region is set read only. + // Access is controlled by writers_lock. +#if defined(COMPONENT_BUILD) + // For component builds writers is a reference to an int defined separately in + // every DSO. + static constexpr int& writers = internal::DsoSpecific::value; +#else + // Otherwise, we declare writers in the protected memory section to avoid the + // scenario where an attacker could overwrite it with a large value and invoke + // code that constructs and destructs an AutoWritableMemory. After such a call + // protected memory would still be set writable because writers > 0. + static int writers; +#endif // defined(COMPONENT_BUILD) + + // Synchronizes access to the writers variable and the simultaneous actions + // that need to happen alongside writers changes, e.g. setting the protected + // memory region readable when writers is decremented to 0. + static Lock& writers_lock() { + static NoDestructor writers_lock; + return *writers_lock; + } + + const raw_ref> protected_memory_; +}; + +#if !defined(COMPONENT_BUILD) +template +PROTECTED_MEMORY_SECTION int AutoWritableMemory::writers = 0; +#endif // !defined(COMPONENT_BUILD) + +template +ProtectedMemory::Initializer::Initializer( + ProtectedMemory* protected_memory, + T&& initial_value) { + AutoWritableMemory writer(*protected_memory); + writer.GetProtectedData() = std::forward(initial_value); +} + +} // namespace base + +#endif // BASE_MEMORY_PROTECTED_MEMORY_H_ diff --git a/naiveproxy/src/base/memory/protected_memory_win.cc b/naiveproxy/src/base/memory/protected_memory_win.cc new file mode 100644 index 0000000000..c6b986c00f --- /dev/null +++ b/naiveproxy/src/base/memory/protected_memory_win.cc @@ -0,0 +1,52 @@ +// Copyright 2024 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/memory/protected_memory.h" + +#include + +#include + +#include "base/memory/page_size.h" +#include "base/process/process_metrics.h" +#include "base/synchronization/lock.h" +#include "build/build_config.h" + +namespace base { +namespace internal { + +namespace { + +bool SetMemory(void* start, void* end, DWORD prot) { + CHECK(end > start); + const uintptr_t page_mask = ~(base::GetPageSize() - 1); + const uintptr_t page_start = reinterpret_cast(start) & page_mask; + DWORD old_prot; + return VirtualProtect(reinterpret_cast(page_start), + reinterpret_cast(end) - page_start, prot, + &old_prot) != 0; +} + +} // namespace + +bool SetMemoryReadWrite(void* start, void* end) { + return SetMemory(start, end, PAGE_READWRITE); +} + +bool SetMemoryReadOnly(void* start, void* end) { + return SetMemory(start, end, PAGE_READONLY); +} + +void AssertMemoryIsReadOnly(const void* ptr) { + const uintptr_t page_mask = ~(base::GetPageSize() - 1); + const uintptr_t page_start = reinterpret_cast(ptr) & page_mask; + + MEMORY_BASIC_INFORMATION info; + SIZE_T result = + VirtualQuery(reinterpret_cast(page_start), &info, sizeof(info)); + CHECK_GT(result, 0U); + CHECK(info.Protect == PAGE_READONLY); +} +} // namespace internal +} // namespace base diff --git a/naiveproxy/src/base/memory/ptr_util.h b/naiveproxy/src/base/memory/ptr_util.h index 5a54886d5d..5b65649dcc 100644 --- a/naiveproxy/src/base/memory/ptr_util.h +++ b/naiveproxy/src/base/memory/ptr_util.h @@ -6,6 +6,7 @@ #define BASE_MEMORY_PTR_UTIL_H_ #include +#include namespace base { @@ -13,6 +14,7 @@ namespace base { // Note that std::unique_ptr has very different semantics from // std::unique_ptr: do not use this helper for array allocations. template + requires(std::is_object_v && !std::is_array_v) std::unique_ptr WrapUnique(T* ptr) { return std::unique_ptr(ptr); } diff --git a/naiveproxy/src/base/memory/raw_ptr.h b/naiveproxy/src/base/memory/raw_ptr.h index aca6d4ac29..9bd2aba438 100644 --- a/naiveproxy/src/base/memory/raw_ptr.h +++ b/naiveproxy/src/base/memory/raw_ptr.h @@ -5,9 +5,14 @@ #ifndef BASE_MEMORY_RAW_PTR_H_ #define BASE_MEMORY_RAW_PTR_H_ +#include "base/compiler_specific.h" + +// TODO(crbug.com/40284755): raw_ptr should use UNSAFE_BUFFERS() internally. +UNSAFE_BUFFERS_INCLUDE_BEGIN // Although `raw_ptr` is part of the standalone PA distribution, it is // easier to use the shorter path in `//base/memory`. We retain this // facade header for ease of typing. #include "base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h" // IWYU pragma: export +UNSAFE_BUFFERS_INCLUDE_END #endif // BASE_MEMORY_RAW_PTR_H_ diff --git a/naiveproxy/src/base/memory/raw_ptr.md b/naiveproxy/src/base/memory/raw_ptr.md index 55ecd9cebe..5bf062e7cf 100644 --- a/naiveproxy/src/base/memory/raw_ptr.md +++ b/naiveproxy/src/base/memory/raw_ptr.md @@ -274,6 +274,11 @@ You don’t have to, but may use `raw_ptr`, in the following scenarios: latter if the collection is a class field (note that some of the perf optimizations above might still apply and argue for using a raw C++ pointer). +### Signal Handlers + +`raw_ptr` assumes that the allocator's data structures are in a consistent +state. Signal handlers can interrupt in the middle of an allocation operation; +therefore, `raw_ptr` should not be used in signal handlers. ## Extra pointer rules {#Extra-pointer-rules} diff --git a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h index 9157fc8e34..f2ca5bbf24 100644 --- a/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h +++ b/naiveproxy/src/base/memory/raw_ptr_asan_bound_arg_tracker.h @@ -19,7 +19,7 @@ namespace base { namespace internal { -template +template struct Invoker; template @@ -55,7 +55,7 @@ class BASE_EXPORT RawPtrAsanBoundArgTracker { static uintptr_t GetProtectedArgPtr(uintptr_t ptr); private: - template + template friend struct internal::Invoker; void Add(uintptr_t pointer); diff --git a/naiveproxy/src/base/memory/raw_ref.h b/naiveproxy/src/base/memory/raw_ref.h index 6cbca47d21..4faa6edb96 100644 --- a/naiveproxy/src/base/memory/raw_ref.h +++ b/naiveproxy/src/base/memory/raw_ref.h @@ -5,9 +5,14 @@ #ifndef BASE_MEMORY_RAW_REF_H_ #define BASE_MEMORY_RAW_REF_H_ +#include "base/compiler_specific.h" + +// TODO(crbug.com/40284755): raw_ref should use UNSAFE_BUFFERS() internally. +UNSAFE_BUFFERS_INCLUDE_BEGIN // Although `raw_ref` is part of the standalone PA distribution, it is // easier to use the shorter path in `//base/memory`. We retain this // facade header for ease of typing. #include "base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h" // IWYU pragma: export +UNSAFE_BUFFERS_INCLUDE_END #endif // BASE_MEMORY_RAW_REF_H_ diff --git a/naiveproxy/src/base/memory/scoped_refptr.h b/naiveproxy/src/base/memory/scoped_refptr.h index 3179e806db..9574bf4a2c 100644 --- a/naiveproxy/src/base/memory/scoped_refptr.h +++ b/naiveproxy/src/base/memory/scoped_refptr.h @@ -339,8 +339,9 @@ class TRIVIAL_ABI scoped_refptr { } protected: - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #union, #addr-of, #global-scope + // RAW_PTR_EXCLUSION: scoped_refptr<> has its own UaF prevention mechanism. + // Given how widespread it is, we it'll likely a perf regression for no + // additional security benefit. RAW_PTR_EXCLUSION T* ptr_ = nullptr; private: diff --git a/naiveproxy/src/base/memory/shared_memory_switch.cc b/naiveproxy/src/base/memory/shared_memory_switch.cc new file mode 100644 index 0000000000..afa3c1c8e0 --- /dev/null +++ b/naiveproxy/src/base/memory/shared_memory_switch.cc @@ -0,0 +1,371 @@ +// Copyright 2024 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/memory/shared_memory_switch.h" + +#include +#include + +#include "base/command_line.h" +#include "base/logging.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/process/launch.h" +#include "base/process/process_handle.h" +#include "base/process/process_info.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/types/expected.h" +#include "base/unguessable_token.h" + +// On Apple platforms, the shared memory handle is shared using a Mach port +// rendezvous key. +#if BUILDFLAG(IS_APPLE) +#include "base/mac/mach_port_rendezvous.h" +#endif + +// On POSIX, the shared memory handle is a file_descriptor mapped in the +// GlobalDescriptors table. +#if BUILDFLAG(IS_POSIX) +#include "base/posix/global_descriptors.h" +#endif + +#if BUILDFLAG(IS_WIN) +#include + +#include "base/win/win_util.h" +#endif + +#if BUILDFLAG(IS_FUCHSIA) +#include +#include + +#include "base/fuchsia/fuchsia_logging.h" +#endif + +// This file supports passing a read/write histogram shared memory region +// between a parent process and child process. The information about the +// shared memory region is encoded into a command-line switch value. +// +// Format: "handle,[irp],guid-high,guid-low,size". +// +// The switch value is composed of 5 segments, separated by commas: +// +// 1. The platform-specific handle id for the shared memory as a string. +// 2. [irp] to indicate whether the handle is inherited (i, most platforms), +// sent via rendezvous (r, MacOS), or should be queried from the parent +// (p, Windows). +// 3. The high 64 bits of the shared memory block GUID. +// 4. The low 64 bits of the shared memory block GUID. +// 5. The size of the shared memory segment as a string. + +namespace base { +namespace shared_memory { +namespace { + +using subtle::PlatformSharedMemoryRegion; +using subtle::ScopedPlatformSharedMemoryHandle; + +// The max shared memory size is artificially limited. This serves as a sanity +// check when serializing/deserializing the handle info. This value should be +// slightly larger than the largest shared memory size used in practice. +constexpr size_t kMaxSharedMemorySize = 8 << 20; // 8 MiB + +// Return a scoped platform shared memory handle for |shmem_region|, possibly +// with permissions reduced to make the handle read-only. +ScopedPlatformSharedMemoryHandle GetPlatformHandle( + PlatformSharedMemoryRegion& shmem_region, + [[maybe_unused]] bool make_read_only) { +#if BUILDFLAG(IS_FUCHSIA) + if (make_read_only) { + // For Fuchsia, ScopedPlatformSharedMemoryHandle <==> zx::vmo + zx::vmo scoped_handle; + zx_status_t status = shmem_region.GetPlatformHandle()->duplicate( + ZX_RIGHT_READ | ZX_RIGHT_MAP | ZX_RIGHT_TRANSFER | + ZX_RIGHT_GET_PROPERTY | ZX_RIGHT_DUPLICATE, + &scoped_handle); + ZX_CHECK(status == ZX_OK, status) << "zx_handle_duplicate"; + return scoped_handle; + } +#endif // BUILDFLAG(IS_FUCHSIA) + return shmem_region.PassPlatformHandle(); +} + +// Serializes the shared memory region metadata to a string that can be added +// to the command-line of a child-process. +std::string Serialize(PlatformSharedMemoryRegion shmem_region, + bool is_read_only, +#if BUILDFLAG(IS_APPLE) + MachPortsForRendezvous::key_type rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + GlobalDescriptors::Key descriptor_key, + ScopedFD& descriptor_to_share, +#endif + [[maybe_unused]] LaunchOptions* launch_options) { +#if !BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_APPLE) + CHECK(launch_options != nullptr); +#endif + + CHECK(shmem_region.IsValid()); + + auto shmem_token = shmem_region.GetGUID(); + auto shmem_size = shmem_region.GetSize(); + auto shmem_handle = GetPlatformHandle(shmem_region, is_read_only); + + CHECK(shmem_token); + CHECK_NE(shmem_size, 0u); + CHECK_LE(shmem_size, kMaxSharedMemorySize); + + // Reserve memory for the serialized value. + // handle,method,hi,lo,size = 4 * 64-bit number + 1 char + 4 commas + NUL + // = (4 * 20-max decimal char) + 6 chars + // = 86 bytes + constexpr size_t kSerializedReservedSize = 86; + + std::string serialized; + serialized.reserve(kSerializedReservedSize); + +#if BUILDFLAG(IS_WIN) + // Ownership of the handle is passed to |launch_options|. We keep a non- + // owning alias for a moment, so we can serialize the handle's numeric + // value. + HANDLE handle = shmem_handle.release(); + launch_options->handles_to_inherit.push_back(handle); + + // Tell the child process the name of the HANDLE and whether to handle can + // be inherited ('i') or must be duplicate from the parent process ('p'). + StrAppend(&serialized, {NumberToString(win::HandleToUint32(handle)), + (launch_options->elevated ? ",p," : ",i,")}); +#elif BUILDFLAG(IS_APPLE) + // In the receiving child, the handle is looked up using the rendezvous key. + launch_options->mach_ports_for_rendezvous.emplace( + rendezvous_key, MachRendezvousPort(std::move(shmem_handle))); + StrAppend(&serialized, {NumberToString(rendezvous_key), ",r,"}); +#elif BUILDFLAG(IS_FUCHSIA) + // The handle is passed via the handles to transfer launch options. The child + // will use the returned handle_id to lookup the handle. Ownership of the + // handle is transferred to |launch_options|. + uint32_t handle_id = LaunchOptions::AddHandleToTransfer( + &launch_options->handles_to_transfer, shmem_handle.release()); + StrAppend(&serialized, {NumberToString(handle_id), ",i,"}); +#elif BUILDFLAG(IS_POSIX) + // Serialize the key by which the child can lookup the shared memory handle. + // Ownership of the handle is transferred, via |descriptor_to_share|, to the + // caller, who is responsible for updating |launch_options| or the zygote + // launch parameters, as appropriate. + // + // TODO(crbug.com/1028263): Create a wrapper to release and return the primary + // descriptor for android (ScopedFD) vs non-android (ScopedFDPair). + // + // TODO(crbug.com/1028263): Get rid of |descriptor_to_share| and just populate + // |launch_options|. The caller should be responsible for translating between + // |launch_options| and zygote parameters as necessary. +#if BUILDFLAG(IS_ANDROID) + descriptor_to_share = std::move(shmem_handle); +#else + descriptor_to_share = std::move(shmem_handle.fd); +#endif + DVLOG(1) << "Sharing fd=" << descriptor_to_share.get() + << " with child process as fd_key=" << descriptor_key; + StrAppend(&serialized, {NumberToString(descriptor_key), ",i,"}); +#else +#error "Unsupported OS" +#endif + + StrAppend(&serialized, + {NumberToString(shmem_token.GetHighForSerialization()), ",", + NumberToString(shmem_token.GetLowForSerialization()), ",", + NumberToString(shmem_size)}); + + DCHECK_LT(serialized.size(), kSerializedReservedSize); + return serialized; +} + +// Deserialize |guid| from |hi_part| and |lo_part|, returning true on success. +std::optional DeserializeGUID(std::string_view hi_part, + std::string_view lo_part) { + uint64_t hi = 0; + uint64_t lo = 0; + if (!StringToUint64(hi_part, &hi) || !StringToUint64(lo_part, &lo)) { + return std::nullopt; + } + return UnguessableToken::Deserialize(hi, lo); +} + +// Deserialize |switch_value| and return a corresponding writable shared memory +// region. On POSIX the handle is passed by |histogram_memory_descriptor_key| +// but |switch_value| is still required to describe the memory region. +expected Deserialize( + std::string_view switch_value, + PlatformSharedMemoryRegion::Mode mode) { + std::vector tokens = + SplitStringPiece(switch_value, ",", KEEP_WHITESPACE, SPLIT_WANT_ALL); + if (tokens.size() != 5) { + return unexpected(SharedMemoryError::kUnexpectedTokensCount); + } + + // Parse the handle from tokens[0]. + uint64_t shmem_handle = 0; + if (!StringToUint64(tokens[0], &shmem_handle)) { + return unexpected(SharedMemoryError::kParseInt0Failed); + } + + // token[1] has a fixed value but is ignored on all platforms except + // Windows, where it can be 'i' or 'p' to indicate that the handle is + // inherited or must be obtained from the parent. +#if BUILDFLAG(IS_WIN) + HANDLE handle = win::Uint32ToHandle(checked_cast(shmem_handle)); + if (tokens[1] == "p") { + DCHECK(IsCurrentProcessElevated()); + // LaunchProcess doesn't have a way to duplicate the handle, but this + // process can since by definition it's not sandboxed. + win::ScopedHandle parent_handle(OpenProcess( + PROCESS_ALL_ACCESS, FALSE, GetParentProcessId(GetCurrentProcess()))); + DuplicateHandle(parent_handle.get(), handle, GetCurrentProcess(), &handle, + 0, FALSE, DUPLICATE_SAME_ACCESS); + } else if (tokens[1] != "i") { + return unexpected(SharedMemoryError::kUnexpectedHandleType); + } + win::ScopedHandle scoped_handle(handle); +#elif BUILDFLAG(IS_APPLE) + DCHECK_EQ(tokens[1], "r"); + auto* rendezvous = MachPortRendezvousClient::GetInstance(); + if (!rendezvous) { + // Note: This matches mojo behavior in content/child/child_thread_impl.cc. + LOG(ERROR) << "No rendezvous client, terminating process (parent died?)"; + Process::TerminateCurrentProcessImmediately(0); + } + apple::ScopedMachSendRight scoped_handle = rendezvous->TakeSendRight( + static_cast(shmem_handle)); + if (!scoped_handle.is_valid()) { + // Note: This matches mojo behavior in content/child/child_thread_impl.cc. + LOG(ERROR) << "Mach rendezvous failed, terminating process (parent died?)"; + base::Process::TerminateCurrentProcessImmediately(0); + } +#elif BUILDFLAG(IS_FUCHSIA) + DCHECK_EQ(tokens[1], "i"); + const uint32_t handle = checked_cast(shmem_handle); + zx::vmo scoped_handle(zx_take_startup_handle(handle)); + if (!scoped_handle.is_valid()) { + LOG(ERROR) << "Invalid shared mem handle: " << handle; + return unexpected(SharedMemoryError::kInvalidHandle); + } +#elif BUILDFLAG(IS_POSIX) + DCHECK_EQ(tokens[1], "i"); + const int fd = GlobalDescriptors::GetInstance()->MaybeGet( + checked_cast(shmem_handle)); + if (fd == -1) { + LOG(ERROR) << "Failed global descriptor lookup: " << shmem_handle; + return unexpected(SharedMemoryError::kGetFDFailed); + } + DVLOG(1) << "Opening shared memory handle " << fd << " shared as " + << shmem_handle; + ScopedFD scoped_handle(fd); +#else +#error Unsupported OS +#endif + + // Together, tokens[2] and tokens[3] encode the shared memory guid. + auto guid = DeserializeGUID(tokens[2], tokens[3]); + if (!guid.has_value()) { + return unexpected(SharedMemoryError::kDeserializeGUIDFailed); + } + + // The size is in tokens[4]. + uint64_t size = 0; + if (!StringToUint64(tokens[4], &size)) { + return unexpected(SharedMemoryError::kParseInt4Failed); + } + if (size == 0 || size > kMaxSharedMemorySize) { + return unexpected(SharedMemoryError::kUnexpectedSize); + } + + // Resolve the handle to a shared memory region. + return PlatformSharedMemoryRegion::Take( + std::move(scoped_handle), mode, checked_cast(size), guid.value()); +} + +} // namespace + +void AddToLaunchParameters(std::string_view switch_name, + ReadOnlySharedMemoryRegion read_only_memory_region, +#if BUILDFLAG(IS_APPLE) + MachPortsForRendezvous::key_type rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + GlobalDescriptors::Key descriptor_key, + ScopedFD& out_descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options) { + std::string switch_value = + Serialize(ReadOnlySharedMemoryRegion::TakeHandleForSerialization( + std::move(read_only_memory_region)), + /*is_read_only=*/true, +#if BUILDFLAG(IS_APPLE) + rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + descriptor_key, out_descriptor_to_share, +#endif + launch_options); + command_line->AppendSwitchASCII(switch_name, switch_value); +} + +void AddToLaunchParameters(std::string_view switch_name, + UnsafeSharedMemoryRegion unsafe_memory_region, +#if BUILDFLAG(IS_APPLE) + MachPortsForRendezvous::key_type rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + GlobalDescriptors::Key descriptor_key, + ScopedFD& out_descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options) { + std::string switch_value = + Serialize(UnsafeSharedMemoryRegion::TakeHandleForSerialization( + std::move(unsafe_memory_region)), + /*is_read_only=*/false, +#if BUILDFLAG(IS_APPLE) + rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + descriptor_key, out_descriptor_to_share, +#endif + launch_options); + command_line->AppendSwitchASCII(switch_name, switch_value); +} + +expected +UnsafeSharedMemoryRegionFrom(std::string_view switch_value) { + auto platform_handle = + Deserialize(switch_value, PlatformSharedMemoryRegion::Mode::kUnsafe); + if (!platform_handle.has_value()) { + return unexpected(platform_handle.error()); + } + auto shmem_region = + UnsafeSharedMemoryRegion::Deserialize(std::move(platform_handle).value()); + if (!shmem_region.IsValid()) { + LOG(ERROR) << "Failed to deserialize writable memory handle"; + return unexpected(SharedMemoryError::kDeserializeFailed); + } + return ok(std::move(shmem_region)); +} + +expected +ReadOnlySharedMemoryRegionFrom(std::string_view switch_value) { + auto platform_handle = + Deserialize(switch_value, PlatformSharedMemoryRegion::Mode::kReadOnly); + if (!platform_handle.has_value()) { + return unexpected(platform_handle.error()); + } + auto shmem_region = ReadOnlySharedMemoryRegion::Deserialize( + std::move(platform_handle).value()); + if (!shmem_region.IsValid()) { + LOG(ERROR) << "Faield to deserialize read-only memory handle"; + return unexpected(SharedMemoryError::kDeserializeFailed); + } + return ok(std::move(shmem_region)); +} + +} // namespace shared_memory +} // namespace base diff --git a/naiveproxy/src/base/memory/shared_memory_switch.h b/naiveproxy/src/base/memory/shared_memory_switch.h new file mode 100644 index 0000000000..617cfc2ccf --- /dev/null +++ b/naiveproxy/src/base/memory/shared_memory_switch.h @@ -0,0 +1,103 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_SHARED_MEMORY_SWITCH_H_ +#define BASE_MEMORY_SHARED_MEMORY_SWITCH_H_ + +#include + +#include "base/base_export.h" +#include "base/memory/read_only_shared_memory_region.h" +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/types/expected.h" +#include "build/blink_buildflags.h" +#include "build/build_config.h" + +#if !BUILDFLAG(USE_BLINK) +#error "This is only intended for platforms that use blink." +#endif + +#if BUILDFLAG(IS_APPLE) +#include "base/mac/mach_port_rendezvous.h" +#endif + +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) +#include "base/files/platform_file.h" +#include "base/posix/global_descriptors.h" +#endif + +namespace base { + +class CommandLine; +struct LaunchOptions; + +namespace shared_memory { + +// Indicates failure modes of deserializing a shared memory switch value. +enum class SharedMemoryError { + kNoError, + kUnexpectedTokensCount, + kParseInt0Failed, + kParseInt4Failed, + kUnexpectedHandleType, + kInvalidHandle, + kGetFDFailed, + kDeserializeGUIDFailed, + kDeserializeFailed, + kCreateTrialsFailed, + kUnexpectedSize, +}; + +// Updates `command_line` and `launch_options` to use `switch_name` to pass +// `read_only_memory_region` to child process that is about to be launched. +// This should be called in the parent process as a part of setting up the +// launch conditions of the child. This call will update the `command_line` +// and `launch_options`. On posix, where we prefer to use a zygote instead of +// using the launch_options to launch a new process, the platform +// `descriptor_to_share` is returned. The caller is expected to transmit the +// descriptor to the launch flow for the zygote. +BASE_EXPORT void AddToLaunchParameters( + std::string_view switch_name, + ReadOnlySharedMemoryRegion read_only_memory_region, +#if BUILDFLAG(IS_APPLE) + MachPortsForRendezvous::key_type rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + GlobalDescriptors::Key descriptor_key, + ScopedFD& out_descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options); + +// Updates `command_line` and `launch_options` to use `switch_name` to pass +// `unsafe_memory_region` to a child process that is about to be launched. +// This should be called in the parent process as a part of setting up the +// launch conditions of the child. This call will update the `command_line` +// and `launch_options`. On posix, where we prefer to use a zygote instead of +// using the launch_options to launch a new process, the platform +// `descriptor_to_share` is returned. The caller is expected to transmit the +// descriptor to the launch flow for the zygote. +BASE_EXPORT void AddToLaunchParameters( + std::string_view switch_name, + UnsafeSharedMemoryRegion unsafe_memory_region, +#if BUILDFLAG(IS_APPLE) + MachPortsForRendezvous::key_type rendezvous_key, +#elif BUILDFLAG(IS_POSIX) + GlobalDescriptors::Key descriptor_key, + ScopedFD& out_descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options); + +// Returns an UnsafeSharedMemoryRegion deserialized from `switch_value`. +BASE_EXPORT expected +UnsafeSharedMemoryRegionFrom(std::string_view switch_value); + +// Returns an ReadOnlySharedMemoryRegion deserialized from `switch_value`. +BASE_EXPORT expected +ReadOnlySharedMemoryRegionFrom(std::string_view switch_value); + +} // namespace shared_memory +} // namespace base + +#endif // BASE_MEMORY_SHARED_MEMORY_SWITCH_H_ diff --git a/naiveproxy/src/base/memory/shared_memory_tracker.cc b/naiveproxy/src/base/memory/shared_memory_tracker.cc index e1f00d5fb4..d1a87ddc92 100644 --- a/naiveproxy/src/base/memory/shared_memory_tracker.cc +++ b/naiveproxy/src/base/memory/shared_memory_tracker.cc @@ -60,7 +60,11 @@ void SharedMemoryTracker::IncrementMemoryUsage( void SharedMemoryTracker::DecrementMemoryUsage( const SharedMemoryMapping& mapping) { AutoLock hold(usages_lock_); - DCHECK(usages_.find(mapping.raw_memory_ptr()) != usages_.end()); + const auto it = usages_.find(mapping.raw_memory_ptr()); + // TODO(pbos): When removing this NotFatalUntil, use erase(it) below. We can't + // do that now because if this CHECK is actually failing there'd be a memory + // bug. + CHECK(it != usages_.end(), base::NotFatalUntil::M125); usages_.erase(mapping.raw_memory_ptr()); } diff --git a/naiveproxy/src/base/memory/weak_ptr.h b/naiveproxy/src/base/memory/weak_ptr.h index 40bd1ca25a..17f9ca6258 100644 --- a/naiveproxy/src/base/memory/weak_ptr.h +++ b/naiveproxy/src/base/memory/weak_ptr.h @@ -84,7 +84,13 @@ #include "base/memory/safe_ref_traits.h" #include "base/sequence_checker.h" #include "base/synchronization/atomic_flag.h" -#include "base/types/pass_key.h" + +namespace performance_manager { +class FrameNodeImpl; +class PageNodeImpl; +class ProcessNodeImpl; +class WorkerNodeImpl; +} // namespace performance_manager namespace base { @@ -294,6 +300,16 @@ class TRIVIAL_ABI WeakPtr { ptr_ = nullptr; } + // Do not use this method. Almost all callers should instead use operator + // bool(). + // + // There are a few rare cases where the caller intentionally needs to check + // validity of a base::WeakPtr on a sequence different from the bound sequence + // as an unavoidable performance optimization. This is the only valid use-case + // for this method. See + // https://docs.google.com/document/d/1IGzq9Nx69GS_2iynGmPWo5sFAD2DcCyBY1zIvZwF7k8 + // for details. + // // Returns false if the WeakPtr is confirmed to be invalid. This call is safe // to make from any thread, e.g. to optimize away unnecessary work, but // RefIsValid() must always be called, on the correct sequence, before @@ -361,6 +377,25 @@ class BASE_EXPORT WeakPtrFactoryBase { }; } // namespace internal +namespace subtle { + +// Restricts access to WeakPtrFactory::BindToCurrentSequence() to authorized +// callers. +class BASE_EXPORT BindWeakPtrFactoryPassKey { + private: + // Avoid =default to disallow creation by uniform initialization. + BindWeakPtrFactoryPassKey() {} + + friend class BindWeakPtrFactoryForTesting; + friend class performance_manager::FrameNodeImpl; + friend class performance_manager::PageNodeImpl; + friend class performance_manager::ProcessNodeImpl; + friend class performance_manager::WorkerNodeImpl; + friend class sequence_manager::internal::TaskQueueImpl; +}; + +} // namespace subtle + // A class may be composed of a WeakPtrFactory and thereby // control how it exposes weak pointers to itself. This is helpful if you only // need weak pointers within the implementation of a class. This class is also @@ -423,11 +458,10 @@ class WeakPtrFactory : public internal::WeakPtrFactoryBase { return weak_reference_owner_.HasRefs(); } - // Rebind the factory to the current sequence. This allows creating a task - // queue and associated weak pointers on a different thread from the one they - // are used on. - void BindToCurrentSequence( - PassKey) { + // Rebind the factory to the current sequence. This allows creating an object + // and associated weak pointers on a different thread from the one they are + // used on. + void BindToCurrentSequence(subtle::BindWeakPtrFactoryPassKey) { weak_reference_owner_.BindToCurrentSequence(); } }; diff --git a/naiveproxy/src/base/memory/weak_ptr_nocompile.nc b/naiveproxy/src/base/memory/weak_ptr_nocompile.nc index 02aebc0341..1659369c41 100644 --- a/naiveproxy/src/base/memory/weak_ptr_nocompile.nc +++ b/naiveproxy/src/base/memory/weak_ptr_nocompile.nc @@ -112,4 +112,11 @@ void VendingMutablePtrsFromConstFactoryDisallowed() { } } +void UnauthorizedBindToCurrentSequenceDisallowed() { + Unrelated unrelated; + WeakPtrFactory factory(&unrelated); + factory.BindToCurrentSequence( + subtle::BindWeakPtrFactoryPassKey()); // expected-error {{calling a private constructor of class 'base::subtle::BindWeakPtrFactoryPassKey'}} +} + } // namespace base diff --git a/naiveproxy/src/base/message_loop/message_pump_epoll.cc b/naiveproxy/src/base/message_loop/message_pump_epoll.cc index 2724cd60a1..1c5a74d8ad 100644 --- a/naiveproxy/src/base/message_loop/message_pump_epoll.cc +++ b/naiveproxy/src/base/message_loop/message_pump_epoll.cc @@ -15,6 +15,7 @@ #include "base/auto_reset.h" #include "base/check_op.h" #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/posix/eintr_wrapper.h" #include "base/ranges/algorithm.h" @@ -88,7 +89,7 @@ bool MessagePumpEpoll::WatchFileDescriptor(int fd, void MessagePumpEpoll::Run(Delegate* delegate) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); RunState run_state(delegate); - AutoReset auto_reset_run_state(&run_state_, &run_state); + AutoReset> auto_reset_run_state(&run_state_, &run_state); for (;;) { // Do some work and see if the next task is ready right away. Delegate::NextWorkInfo next_work_info = delegate->DoWork(); @@ -97,8 +98,11 @@ void MessagePumpEpoll::Run(Delegate* delegate) { break; } + // Reset the native work flag before processing IO events. + native_work_started_ = false; + // Process any immediately ready IO event, but don't wait for more yet. - WaitForEpollEvents(TimeDelta(), delegate); + WaitForEpollEvents(TimeDelta()); bool attempt_more_work = immediate_work_available || processed_io_events_; processed_io_events_ = false; @@ -125,7 +129,7 @@ void MessagePumpEpoll::Run(Delegate* delegate) { timeout = next_work_info.remaining_delay(); } delegate->BeforeWait(); - WaitForEpollEvents(timeout, delegate); + WaitForEpollEvents(timeout); if (run_state.should_quit) { break; } @@ -204,12 +208,12 @@ void MessagePumpEpoll::UnregisterInterest( const int fd = interest->params().fd; auto entry_it = entries_.find(fd); - DCHECK(entry_it != entries_.end()); + CHECK(entry_it != entries_.end(), base::NotFatalUntil::M125); EpollEventEntry& entry = entry_it->second; auto& interests = entry.interests; auto* it = ranges::find(interests, interest); - DCHECK(it != interests.end()); + CHECK(it != interests.end(), base::NotFatalUntil::M125); interests.erase(it); if (interests.empty()) { @@ -220,8 +224,7 @@ void MessagePumpEpoll::UnregisterInterest( } } -bool MessagePumpEpoll::WaitForEpollEvents(TimeDelta timeout, - Delegate* delegate) { +bool MessagePumpEpoll::WaitForEpollEvents(TimeDelta timeout) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // `timeout` has microsecond resolution, but timeouts accepted by epoll_wait() @@ -242,7 +245,6 @@ bool MessagePumpEpoll::WaitForEpollEvents(TimeDelta timeout, return false; } - delegate->BeginNativeWorkBeforeDoWork(); const base::span ready_events(events, static_cast(epoll_result)); for (auto& e : ready_events) { @@ -348,6 +350,7 @@ void MessagePumpEpoll::HandleEvent(int fd, bool can_write, FdWatchController* controller) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + BeginNativeWorkBatch(); processed_io_events_ = true; // Make the MessagePumpDelegate aware of this other form of "DoWork". Skip if // HandleNotification() is called outside of Run() (e.g. in unit tests). @@ -387,12 +390,24 @@ void MessagePumpEpoll::HandleEvent(int fd, void MessagePumpEpoll::HandleWakeUp() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + BeginNativeWorkBatch(); processed_io_events_ = true; uint64_t value; ssize_t n = HANDLE_EINTR(read(wake_event_.get(), &value, sizeof(value))); DPCHECK(n == sizeof(value)); } +void MessagePumpEpoll::BeginNativeWorkBatch() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + // Call `BeginNativeWorkBeforeDoWork()` if native work hasn't started. + if (!native_work_started_) { + if (run_state_) { + run_state_->delegate->BeginNativeWorkBeforeDoWork(); + } + native_work_started_ = true; + } +} + MessagePumpEpoll::EpollEventEntry::EpollEventEntry(int fd) : fd(fd) {} MessagePumpEpoll::EpollEventEntry::~EpollEventEntry() { diff --git a/naiveproxy/src/base/message_loop/message_pump_epoll.h b/naiveproxy/src/base/message_loop/message_pump_epoll.h index 6a91c7d9bc..56707328b0 100644 --- a/naiveproxy/src/base/message_loop/message_pump_epoll.h +++ b/naiveproxy/src/base/message_loop/message_pump_epoll.h @@ -125,7 +125,7 @@ class BASE_EXPORT MessagePumpEpoll : public MessagePump, void UpdateEpollEvent(EpollEventEntry& entry); void StopEpollEvent(EpollEventEntry& entry); void UnregisterInterest(const scoped_refptr& interest); - bool WaitForEpollEvents(TimeDelta timeout, Delegate* delegate); + bool WaitForEpollEvents(TimeDelta timeout); void OnEpollEvent(EpollEventEntry& entry, uint32_t events); void HandleEvent(int fd, bool can_read, @@ -133,15 +133,19 @@ class BASE_EXPORT MessagePumpEpoll : public MessagePump, FdWatchController* controller); void HandleWakeUp(); + void BeginNativeWorkBatch(); + // Null if Run() is not currently executing. Otherwise it's a pointer into the // stack of the innermost nested Run() invocation. - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION RunState* run_state_ = nullptr; + raw_ptr run_state_ = nullptr; // This flag is set if epoll has processed I/O events. bool processed_io_events_ = false; + // This flag is set when starting to process native work; reset after every + // `DoWork()` call. See crbug.com/1500295. + bool native_work_started_ = false; + // Mapping of all file descriptors currently watched by this message pump. // std::map was chosen because (1) the number of elements can vary widely, // (2) we don't do frequent lookups, and (3) values need stable addresses diff --git a/naiveproxy/src/base/message_loop/message_pump_libevent.cc b/naiveproxy/src/base/message_loop/message_pump_libevent.cc index 2ddec92744..fc029b6963 100644 --- a/naiveproxy/src/base/message_loop/message_pump_libevent.cc +++ b/naiveproxy/src/base/message_loop/message_pump_libevent.cc @@ -14,6 +14,7 @@ #include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/logging.h" +#include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" #include "base/time/time.h" @@ -153,11 +154,6 @@ MessagePumpLibevent::MessagePumpLibevent() { DCHECK(wakeup_event_); } -#if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL) -MessagePumpLibevent::MessagePumpLibevent(decltype(kUseEpoll)) - : epoll_pump_(std::make_unique()) {} -#endif - MessagePumpLibevent::~MessagePumpLibevent() { #if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL) const bool using_libevent = !epoll_pump_; @@ -281,7 +277,7 @@ void MessagePumpLibevent::Run(Delegate* delegate) { #endif RunState run_state(delegate); - AutoReset auto_reset_run_state(&run_state_, &run_state); + AutoReset> auto_reset_run_state(&run_state_, &run_state); // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. // Instead, make our own timer and reuse it on each call to event_base_loop(). diff --git a/naiveproxy/src/base/message_loop/message_pump_libevent.h b/naiveproxy/src/base/message_loop/message_pump_libevent.h index 548477d85f..0b37f380ef 100644 --- a/naiveproxy/src/base/message_loop/message_pump_libevent.h +++ b/naiveproxy/src/base/message_loop/message_pump_libevent.h @@ -83,12 +83,23 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump, bool was_controller_destroyed() const { return was_controller_destroyed_; } void WatchForControllerDestruction() { - DCHECK(!controller_->was_destroyed_); - controller_->was_destroyed_ = &was_controller_destroyed_; + DCHECK_GE(nested_controller_destruction_watchers_, 0); + if (nested_controller_destruction_watchers_ == 0) { + DCHECK(!controller_->was_destroyed_); + controller_->was_destroyed_ = &was_controller_destroyed_; + } else { + // If this is a nested event we should already be watching `controller_` + // for destruction from an outer event handler. + DCHECK_EQ(controller_->was_destroyed_, &was_controller_destroyed_); + } + ++nested_controller_destruction_watchers_; } void StopWatchingForControllerDestruction() { - if (!was_controller_destroyed_) { + --nested_controller_destruction_watchers_; + DCHECK_GE(nested_controller_destruction_watchers_, 0); + if (nested_controller_destruction_watchers_ == 0 && + !was_controller_destroyed_) { DCHECK_EQ(controller_->was_destroyed_, &was_controller_destroyed_); controller_->was_destroyed_ = nullptr; } @@ -102,6 +113,10 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump, const EpollInterestParams params_; bool active_ = true; bool was_controller_destroyed_ = false; + + // Avoid resetting `controller_->was_destroyed` when nested destruction + // watchers are active. + int nested_controller_destruction_watchers_ = 0; }; // Note that this class is used as the FdWatchController for both @@ -179,13 +194,6 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump, MessagePumpLibevent(); -#if BUILDFLAG(ENABLE_MESSAGE_PUMP_EPOLL) - // Constructs a MessagePumpLibevent which is forced to use epoll directly - // instead of libevent. - enum { kUseEpoll }; - explicit MessagePumpLibevent(decltype(kUseEpoll)); -#endif - MessagePumpLibevent(const MessagePumpLibevent&) = delete; MessagePumpLibevent& operator=(const MessagePumpLibevent&) = delete; @@ -225,8 +233,8 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump, struct RunState { explicit RunState(Delegate* delegate_in) : delegate(delegate_in) {} - // `delegate` is not a raw_ptr<...> for performance reasons (based on - // analysis of sampling profiler data and tab_search:top100:2020). + // RAW_PTR_EXCLUSION: Performance reasons (based on analysis of sampling + // profiler data and tab_search:top100:2020). RAW_PTR_EXCLUSION Delegate* const delegate; // Used to flag that the current Run() invocation should return ASAP. @@ -240,10 +248,7 @@ class BASE_EXPORT MessagePumpLibevent : public MessagePump, std::unique_ptr epoll_pump_; #endif - // State for the current invocation of Run(). null if not running. - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION RunState* run_state_ = nullptr; + raw_ptr run_state_ = nullptr; // This flag is set if libevent has processed I/O events. bool processed_io_events_ = false; diff --git a/naiveproxy/src/base/message_loop/message_pump_win.cc b/naiveproxy/src/base/message_loop/message_pump_win.cc index c30066f515..2f07a96035 100644 --- a/naiveproxy/src/base/message_loop/message_pump_win.cc +++ b/naiveproxy/src/base/message_loop/message_pump_win.cc @@ -13,6 +13,7 @@ #include "base/debug/alias.h" #include "base/feature_list.h" #include "base/functional/bind.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/trace_event/base_tracing.h" @@ -74,7 +75,7 @@ void MessagePumpWin::Run(Delegate* delegate) { if (run_state_) run_state.is_nested = true; - AutoReset auto_reset_run_state(&run_state_, &run_state); + AutoReset> auto_reset_run_state(&run_state_, &run_state); DoRunLoop(); } @@ -299,9 +300,13 @@ void MessagePumpForUI::WaitForWork(Delegate::NextWorkInfo next_work_info) { wait_flags = 0; } else { last_wakeup_was_spurious = true; - TRACE_EVENT_INSTANT("base", - "MessagePumpForUI::WaitForWork Spurious Wakeup", - "reason: ", result); + TRACE_EVENT_INSTANT( + "base", "MessagePumpForUI::WaitForWork Spurious Wakeup", + [&](perfetto::EventContext ctx) { + ctx.event() + ->set_chrome_message_pump_for_ui() + ->set_wait_for_object_result(result); + }); } DCHECK_NE(WAIT_FAILED, result) << GetLastError(); diff --git a/naiveproxy/src/base/message_loop/message_pump_win.h b/naiveproxy/src/base/message_loop/message_pump_win.h index 68afdb2363..5ef23731ab 100644 --- a/naiveproxy/src/base/message_loop/message_pump_win.h +++ b/naiveproxy/src/base/message_loop/message_pump_win.h @@ -14,7 +14,6 @@ #include "base/compiler_specific.h" #include "base/location.h" #include "base/memory/raw_ptr.h" -#include "base/memory/raw_ptr_exclusion.h" #include "base/message_loop/message_pump.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" @@ -76,10 +75,7 @@ class BASE_EXPORT MessagePumpWin : public MessagePump { // this is simpler than MessagePumpForUI. std::atomic_bool work_scheduled_{false}; - // State for the current invocation of Run(). null if not running. - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION RunState* run_state_ = nullptr; + raw_ptr run_state_ = nullptr; THREAD_CHECKER(bound_thread_); }; diff --git a/naiveproxy/src/base/metrics/field_trial.cc b/naiveproxy/src/base/metrics/field_trial.cc index 103e646044..85a8e43f0b 100644 --- a/naiveproxy/src/base/metrics/field_trial.cc +++ b/naiveproxy/src/base/metrics/field_trial.cc @@ -35,6 +35,7 @@ #include "build/build_config.h" #if BUILDFLAG(USE_BLINK) +#include "base/memory/shared_memory_switch.h" #include "base/process/launch.h" #endif @@ -64,6 +65,10 @@ namespace base { namespace { +#if BUILDFLAG(USE_BLINK) +using shared_memory::SharedMemoryError; +#endif + // Define a separator character to use when creating a persistent form of an // instance. This is intended for use as a command line argument, passed to a // second process to mimic our state (i.e., provide the same group name). @@ -140,28 +145,6 @@ void OnOutOfMemory(size_t size) { TerminateBecauseOutOfMemory(size); } -#if BUILDFLAG(USE_BLINK) -// Returns whether the operation succeeded. -bool DeserializeGUIDFromStringPieces(StringPiece first, - StringPiece second, - UnguessableToken* guid) { - uint64_t high = 0; - uint64_t low = 0; - if (!StringToUint64(first, &high) || !StringToUint64(second, &low)) { - return false; - } - - absl::optional token = - UnguessableToken::Deserialize(high, low); - if (!token.has_value()) { - return false; - } - - *guid = token.value(); - return true; -} -#endif // BUILDFLAG(USE_BLINK) - void AppendFieldTrialGroupToString(bool activated, std::string_view trial_name, std::string_view group_name, @@ -710,8 +693,8 @@ bool FieldTrialList::CreateTrialsFromFieldTrialStates( } // static -void FieldTrialList::CreateTrialsInChildProcess(const CommandLine& cmd_line, - uint32_t fd_key) { +void FieldTrialList::CreateTrialsInChildProcess(const CommandLine& cmd_line) { + CHECK(!global_->create_trials_in_child_process_called_); global_->create_trials_in_child_process_called_ = true; #if BUILDFLAG(USE_BLINK) @@ -719,10 +702,10 @@ void FieldTrialList::CreateTrialsInChildProcess(const CommandLine& cmd_line, if (cmd_line.HasSwitch(switches::kFieldTrialHandle)) { std::string switch_value = cmd_line.GetSwitchValueASCII(switches::kFieldTrialHandle); - SharedMemError result = CreateTrialsFromSwitchValue(switch_value, fd_key); - SCOPED_CRASH_KEY_NUMBER("FieldTrialList", "SharedMemError", + SharedMemoryError result = CreateTrialsFromSwitchValue(switch_value); + SCOPED_CRASH_KEY_NUMBER("FieldTrialList", "SharedMemoryError", static_cast(result)); - CHECK_EQ(result, SharedMemError::kNoError); + CHECK_EQ(result, SharedMemoryError::kNoError); } #endif // BUILDFLAG(USE_BLINK) } @@ -740,6 +723,10 @@ void FieldTrialList::ApplyFeatureOverridesInChildProcess( #if BUILDFLAG(USE_BLINK) // static void FieldTrialList::PopulateLaunchOptionsWithFieldTrialState( +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) + GlobalDescriptors::Key descriptor_key, + ScopedFD& descriptor_to_share, +#endif CommandLine* command_line, LaunchOptions* launch_options) { CHECK(command_line); @@ -751,9 +738,15 @@ void FieldTrialList::PopulateLaunchOptionsWithFieldTrialState( CHECK(global_->readonly_allocator_region_.IsValid()); global_->field_trial_allocator_->UpdateTrackingHistograms(); - std::string switch_value = SerializeSharedMemoryRegionMetadata( - global_->readonly_allocator_region_, launch_options); - command_line->AppendSwitchASCII(switches::kFieldTrialHandle, switch_value); + shared_memory::AddToLaunchParameters( + switches::kFieldTrialHandle, + global_->readonly_allocator_region_.Duplicate(), +#if BUILDFLAG(IS_APPLE) + kFieldTrialRendezvousKey, +#elif BUILDFLAG(IS_POSIX) + descriptor_key, descriptor_to_share, +#endif + command_line, launch_options); // Append --enable-features and --disable-features switches corresponding // to the features enabled on the command-line, so that child and browser @@ -775,21 +768,6 @@ void FieldTrialList::PopulateLaunchOptionsWithFieldTrialState( } #endif // BUILDFLAG(USE_BLINK) -#if BUILDFLAG(USE_BLINK) && BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) -// static -int FieldTrialList::GetFieldTrialDescriptor() { - InstantiateFieldTrialAllocatorIfNeeded(); - if (!global_ || !global_->readonly_allocator_region_.IsValid()) - return -1; - -#if BUILDFLAG(IS_ANDROID) - return global_->readonly_allocator_region_.GetPlatformHandle(); -#else - return global_->readonly_allocator_region_.GetPlatformHandle().fd; -#endif -} -#endif // BUILDFLAG(USE_BLINK) && BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) - // static ReadOnlySharedMemoryRegion FieldTrialList::DuplicateFieldTrialSharedMemoryForTesting() { @@ -1061,166 +1039,16 @@ void FieldTrialList::RestoreInstanceForTesting(FieldTrialList* instance) { #if BUILDFLAG(USE_BLINK) // static -std::string FieldTrialList::SerializeSharedMemoryRegionMetadata( - const ReadOnlySharedMemoryRegion& shm, - LaunchOptions* launch_options) { - std::stringstream ss; -#if BUILDFLAG(IS_WIN) - // Elevated process might not need this, although it is harmless. - launch_options->handles_to_inherit.push_back(shm.GetPlatformHandle()); - - // Tell the child process the name of the inherited HANDLE. - uintptr_t uintptr_handle = - reinterpret_cast(shm.GetPlatformHandle()); - ss << uintptr_handle << ","; - if (launch_options->elevated) { - // Tell the child that it must open its parent and grab the handle. - ss << "p,"; - } else { - // Tell the child that it inherited the handle. - ss << "i,"; - } -#elif BUILDFLAG(IS_APPLE) - launch_options->mach_ports_for_rendezvous.emplace( - kFieldTrialRendezvousKey, - MachRendezvousPort(shm.GetPlatformHandle(), MACH_MSG_TYPE_COPY_SEND)); - - // The handle on Mac is looked up directly by the child, rather than being - // transferred to the child over the command line. - ss << kFieldTrialRendezvousKey << ","; - // Tell the child that the handle is looked up. - ss << "r,"; -#elif BUILDFLAG(IS_FUCHSIA) - zx::vmo transfer_vmo; - zx_status_t status = shm.GetPlatformHandle()->duplicate( - ZX_RIGHT_READ | ZX_RIGHT_MAP | ZX_RIGHT_TRANSFER | ZX_RIGHT_GET_PROPERTY | - ZX_RIGHT_DUPLICATE, - &transfer_vmo); - ZX_CHECK(status == ZX_OK, status) << "zx_handle_duplicate"; - - // The handle on Fuchsia is passed as part of the launch handles to transfer. - uint32_t handle_id = LaunchOptions::AddHandleToTransfer( - &launch_options->handles_to_transfer, transfer_vmo.release()); - ss << handle_id << ","; - // Tell the child that the handle is inherited. - ss << "i,"; -#elif BUILDFLAG(IS_POSIX) - // This is actually unused in the child process, but allows non-Mac Posix - // platforms to have the same format as the others. - ss << "0,i,"; -#else -#error Unsupported OS -#endif - - UnguessableToken guid = shm.GetGUID(); - ss << guid.GetHighForSerialization() << "," << guid.GetLowForSerialization(); - ss << "," << shm.GetSize(); - return ss.str(); -} - -// static -expected -FieldTrialList::DeserializeSharedMemoryRegionMetadata( - const std::string& switch_value, - uint32_t fd_key) { - // Format: "handle,[irp],guid-high,guid-low,size". - std::vector tokens = - SplitStringPiece(switch_value, ",", KEEP_WHITESPACE, SPLIT_WANT_ALL); - - if (tokens.size() != 5) { - return base::unexpected(SharedMemError::kUnexpectedTokensCount); - } - - int field_trial_handle = 0; - if (!StringToInt(tokens[0], &field_trial_handle)) { - return base::unexpected(SharedMemError::kParseInt0Failed); - } - - // token[1] has a fixed value but is ignored on all platforms except - // Windows, where it can be 'i' or 'p' to indicate that the handle is - // inherited or must be obtained from the parent. -#if BUILDFLAG(IS_WIN) - HANDLE handle = reinterpret_cast(field_trial_handle); - if (tokens[1] == "p") { - DCHECK(IsCurrentProcessElevated()); - // LaunchProcess doesn't have a way to duplicate the handle, but this - // process can since by definition it's not sandboxed. - ProcessId parent_pid = GetParentProcessId(GetCurrentProcess()); - HANDLE parent_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, parent_pid); - // TODO(https://crbug.com/916461): Duplicating the handle is known to fail - // with ERROR_ACCESS_DENIED when the parent process is being torn down. This - // should be handled elegantly somehow. - DuplicateHandle(parent_handle, handle, GetCurrentProcess(), &handle, 0, - FALSE, DUPLICATE_SAME_ACCESS); - CloseHandle(parent_handle); - } else if (tokens[1] != "i") { - return base::unexpected(SharedMemError::kUnexpectedHandleType); - } - win::ScopedHandle scoped_handle(handle); -#elif BUILDFLAG(IS_APPLE) && BUILDFLAG(USE_BLINK) - auto* rendezvous = MachPortRendezvousClient::GetInstance(); - if (!rendezvous) { - LOG(ERROR) << "Mach rendezvous failed, terminating process (parent died?)"; - base::Process::TerminateCurrentProcessImmediately(0); - } - apple::ScopedMachSendRight scoped_handle = rendezvous->TakeSendRight( - static_cast(field_trial_handle)); - if (!scoped_handle.is_valid()) { - return base::unexpected(SharedMemError::kInvalidHandle); - } -#elif BUILDFLAG(IS_FUCHSIA) - static bool startup_handle_taken = false; - DCHECK(!startup_handle_taken) << "Shared memory region initialized twice"; - zx::vmo scoped_handle( - zx_take_startup_handle(checked_cast(field_trial_handle))); - startup_handle_taken = true; - if (!scoped_handle.is_valid()) { - return base::unexpected(SharedMemError::kInvalidHandle); - } -#elif BUILDFLAG(IS_POSIX) - int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); - if (fd == -1) { - return base::unexpected(SharedMemError::kGetFDFailed); - } - ScopedFD scoped_handle(fd); -#else -#error Unsupported OS -#endif - - UnguessableToken guid; - if (!DeserializeGUIDFromStringPieces(tokens[2], tokens[3], &guid)) { - return base::unexpected(SharedMemError::kDeserializeGUIDFailed); - } - - int size; - if (!StringToInt(tokens[4], &size)) { - return base::unexpected(SharedMemError::kParseInt4Failed); - } - - auto platform_handle = subtle::PlatformSharedMemoryRegion::Take( - std::move(scoped_handle), - subtle::PlatformSharedMemoryRegion::Mode::kReadOnly, - static_cast(size), guid); - ReadOnlySharedMemoryRegion shm = - ReadOnlySharedMemoryRegion::Deserialize(std::move(platform_handle)); - if (!shm.IsValid()) { - return base::unexpected(SharedMemError::kDeserializeFailed); - } - return base::ok(std::move(shm)); -} - -// static -FieldTrialList::SharedMemError FieldTrialList::CreateTrialsFromSwitchValue( - const std::string& switch_value, - uint32_t fd_key) { - auto shm = DeserializeSharedMemoryRegionMetadata(switch_value, fd_key); +SharedMemoryError FieldTrialList::CreateTrialsFromSwitchValue( + const std::string& switch_value) { + auto shm = shared_memory::ReadOnlySharedMemoryRegionFrom(switch_value); if (!shm.has_value()) { return shm.error(); } if (!FieldTrialList::CreateTrialsFromSharedMemoryRegion(shm.value())) { - return SharedMemError::kCreateTrialsFailed; + return SharedMemoryError::kCreateTrialsFailed; } - return SharedMemError::kNoError; + return SharedMemoryError::kNoError; } #endif // BUILDFLAG(USE_BLINK) diff --git a/naiveproxy/src/base/metrics/field_trial.h b/naiveproxy/src/base/metrics/field_trial.h index ca32a5ef7b..3a3a3f01c8 100644 --- a/naiveproxy/src/base/metrics/field_trial.h +++ b/naiveproxy/src/base/metrics/field_trial.h @@ -96,6 +96,11 @@ #include "build/blink_buildflags.h" #include "build/build_config.h" +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) +#include "base/files/platform_file.h" +#include "base/posix/global_descriptors.h" +#endif + namespace base { namespace test { @@ -106,6 +111,12 @@ class CompareActiveGroupToFieldTrialMatcher; class FieldTrialList; struct LaunchOptions; +#if BUILDFLAG(USE_BLINK) +namespace shared_memory { +enum class SharedMemoryError; +} // namespace shared_memory +#endif + class BASE_EXPORT FieldTrial : public RefCounted { public: typedef int Probability; // Probability type for being selected in a trial. @@ -590,14 +601,7 @@ class BASE_EXPORT FieldTrialList { // via PopulateLaunchOptionsWithFieldTrialState() in the parent process. // Trials are retrieved from a shared memory segment that has been shared with // the child process. - // - // `fd_key` is used on non-Mac POSIX platforms to access the shared memory - // segment and ignored on other platforms. The argument is needed here since - // //base can't depend on //content. On other platforms, we expect the - // `cmd_line` switch for kFieldTrialHandle to contain the shared memory handle - // that contains the field trial allocator. - static void CreateTrialsInChildProcess(const CommandLine& cmd_line, - uint32_t fd_key); + static void CreateTrialsInChildProcess(const CommandLine& cmd_line); // Creates base::Feature overrides in a child process using shared memory. // Requires CreateTrialsInChildProcess() to have been called first which @@ -609,18 +613,14 @@ class BASE_EXPORT FieldTrialList { // line arguments necessary for a child process to inherit the shared-memory // object containing the FieldTrial configuration. static void PopulateLaunchOptionsWithFieldTrialState( +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) + GlobalDescriptors::Key descriptor_key, + ScopedFD& descriptor_to_share, +#endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) CommandLine* command_line, LaunchOptions* launch_options); #endif // !BUILDFLAG(USE_BLINK) -#if BUILDFLAG(USE_BLINK) && BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) - // On POSIX, we also need to explicitly pass down this file descriptor that - // should be shared with the child process. Returns -1 if it was not - // initialized properly. The current process remains the owner of the passed - // descriptor. - static int GetFieldTrialDescriptor(); -#endif // BUILDFLAG(USE_BLINK) && BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) - static ReadOnlySharedMemoryRegion DuplicateFieldTrialSharedMemoryForTesting(); // Create a FieldTrial with the given |name| and using 100% probability for @@ -757,38 +757,12 @@ class BASE_EXPORT FieldTrialList { const ReadOnlySharedMemoryRegion& shm, LaunchOptions* launch_options); - // Indicates failure modes of deserializing the shared memory handle. - enum class SharedMemError { - kNoError, - kUnexpectedTokensCount, - kParseInt0Failed, - kParseInt4Failed, - kUnexpectedHandleType, - kInvalidHandle, - kGetFDFailed, - kDeserializeGUIDFailed, - kDeserializeFailed, - kCreateTrialsFailed, - }; - - // Deserialization instantiates the shared memory region for FieldTrials from - // the serialized information contained in |switch_value|. Returns an invalid - // ReadOnlySharedMemoryRegion on failure. - // |fd_key| is used on non-Mac POSIX platforms as the file descriptor passed - // down to the child process for the shared memory region. - static expected - DeserializeSharedMemoryRegionMetadata(const std::string& switch_value, - uint32_t fd_key); - // Takes in |handle_switch| from the command line which represents the shared // memory handle for field trials, parses it, and creates the field trials. // Returns true on success, false on failure. // |switch_value| also contains the serialized GUID. - // |fd_key| is used on non-Mac POSIX platforms as the file descriptor passed - // down to the child process for the shared memory region. - static SharedMemError CreateTrialsFromSwitchValue( - const std::string& switch_value, - uint32_t fd_key); + static base::shared_memory::SharedMemoryError CreateTrialsFromSwitchValue( + const std::string& switch_value); #endif // BUILDFLAG(USE_BLINK) // Takes an unmapped ReadOnlySharedMemoryRegion, maps it with the correct size diff --git a/naiveproxy/src/base/metrics/histogram_samples.cc b/naiveproxy/src/base/metrics/histogram_samples.cc index 76aa633fdb..f4749f77d3 100644 --- a/naiveproxy/src/base/metrics/histogram_samples.cc +++ b/naiveproxy/src/base/metrics/histogram_samples.cc @@ -5,6 +5,7 @@ #include "base/metrics/histogram_samples.h" #include +#include #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" @@ -13,6 +14,8 @@ #include "base/numerics/safe_conversions.h" #include "base/numerics/safe_math.h" #include "base/pickle.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" namespace base { @@ -356,9 +359,8 @@ base::Value::Dict HistogramSamples::ToGraphDict(StringPiece histogram_name, std::string HistogramSamples::GetAsciiHeader(StringPiece histogram_name, int32_t flags) const { std::string output; - StringAppendF(&output, "Histogram: %.*s recorded %d samples", - static_cast(histogram_name.size()), histogram_name.data(), - TotalCount()); + StrAppend(&output, {"Histogram: ", histogram_name, " recorded ", + NumberToString(TotalCount()), " samples"}); if (flags) StringAppendF(&output, " (flags = 0x%x)", flags); return output; @@ -406,12 +408,13 @@ std::string HistogramSamples::GetAsciiBody() const { // value is min, so display it std::string range = GetSimpleAsciiBucketRange(min); output.append(range); - for (size_t j = 0; range.size() + j < print_width + 1; ++j) - output.push_back(' '); + if (const auto range_size = range.size(); print_width >= range_size) { + output.append(print_width + 1 - range_size, ' '); + } HistogramBase::Count current_size = round(count * scaling_factor); WriteAsciiBucketGraph(current_size, kLineLength, &output); WriteAsciiBucketValue(count, scaled_total_count, &output); - StringAppendF(&output, "\n"); + output.append(1, '\n'); it->Next(); } return output; @@ -420,13 +423,12 @@ std::string HistogramSamples::GetAsciiBody() const { void HistogramSamples::WriteAsciiBucketGraph(double x_count, int line_length, std::string* output) const { - int x_remainder = line_length - x_count; + int x_remainder = std::max(line_length - x_count, 0.0); - while (0 < x_count--) - output->append("-"); - output->append("O"); - while (0 < x_remainder--) - output->append(" "); + output->reserve(output->size() + x_count + 1 + x_remainder); + output->append(x_count, '-'); + output->append(1, 'O'); + output->append(saturated_cast(x_remainder), ' '); } void HistogramSamples::WriteAsciiBucketValue(HistogramBase::Count current, diff --git a/naiveproxy/src/base/metrics/histogram_shared_memory.cc b/naiveproxy/src/base/metrics/histogram_shared_memory.cc index 67bf4becb3..f4afd0047e 100644 --- a/naiveproxy/src/base/metrics/histogram_shared_memory.cc +++ b/naiveproxy/src/base/metrics/histogram_shared_memory.cc @@ -4,59 +4,199 @@ #include "base/metrics/histogram_shared_memory.h" -#include "base/memory/shared_memory_mapping.h" +#include +#include "base/base_switches.h" +#include "base/debug/crash_logging.h" +#include "base/memory/shared_memory_mapping.h" +#include "base/memory/shared_memory_switch.h" +#include "base/memory/writable_shared_memory_region.h" +#include "base/metrics/histogram_macros_local.h" +#include "base/metrics/persistent_histogram_allocator.h" +#include "base/metrics/persistent_memory_allocator.h" +#include "base/process/launch.h" +#include "base/process/process_handle.h" +#include "base/process/process_info.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/unguessable_token.h" + +// On Apple platforms, the shared memory handle is shared using a Mach port +// rendezvous key. +#if BUILDFLAG(IS_APPLE) +#include "base/mac/mach_port_rendezvous.h" +#endif + +// On POSIX, the shared memory handle is a file_descriptor mapped in the +// GlobalDescriptors table. +#if BUILDFLAG(IS_POSIX) +#include "base/posix/global_descriptors.h" +#endif + +#if BUILDFLAG(IS_WIN) +#include + +#include "base/win/win_util.h" +#endif + +#if BUILDFLAG(IS_FUCHSIA) +#include +#include + +#include "base/fuchsia/fuchsia_logging.h" +#endif + +// This file supports passing a read/write histogram shared memory region +// between a parent process and child process. The information about the +// shared memory region is encoded into a command-line switch value. +// +// Format: "handle,[irp],guid-high,guid-low,size". +// +// The switch value is composed of 5 segments, separated by commas: +// +// 1. The platform-specific handle id for the shared memory as a string. +// 2. [irp] to indicate whether the handle is inherited (i, most platforms), +// sent via rendezvous (r, MacOS), or should be queried from the parent +// (p, Windows). +// 3. The high 64 bits of the shared memory block GUID. +// 4. The low 64 bits of the shared memory block GUID. +// 5. The size of the shared memory segment as a string. +// +// TODO(crbug.com/1028263): Refactor the common logic here and in +// base/metrics/field_trial.cc namespace base { -HistogramSharedMemory::HistogramSharedMemory() = default; -HistogramSharedMemory::~HistogramSharedMemory() = default; -HistogramSharedMemory::HistogramSharedMemory(HistogramSharedMemory&& other) = - default; -HistogramSharedMemory& HistogramSharedMemory::operator=( - HistogramSharedMemory&& other) = default; +BASE_FEATURE(kPassHistogramSharedMemoryOnLaunch, + "PassHistogramSharedMemoryOnLaunch", + FEATURE_DISABLED_BY_DEFAULT); + +#if BUILDFLAG(IS_APPLE) +const MachPortsForRendezvous::key_type HistogramSharedMemory::kRendezvousKey = + 'hsmr'; +#endif + +HistogramSharedMemory::SharedMemory::SharedMemory( + UnsafeSharedMemoryRegion r, + std::unique_ptr a) + : region(std::move(r)), allocator(std::move(a)) { + CHECK(region.IsValid()); + CHECK(allocator); +} + +HistogramSharedMemory::SharedMemory::~SharedMemory() = default; + +HistogramSharedMemory::SharedMemory::SharedMemory( + HistogramSharedMemory::SharedMemory&&) = default; + +HistogramSharedMemory::SharedMemory& +HistogramSharedMemory::SharedMemory::operator=( + HistogramSharedMemory::SharedMemory&&) = default; // static -absl::optional HistogramSharedMemory::Create( - int unique_process_id, - const HistogramSharedMemoryConfig& config) { - auto shared_memory_region = - base::WritableSharedMemoryRegion::Create(config.memory_size_bytes); - if (!shared_memory_region.IsValid()) { +absl::optional +HistogramSharedMemory::Create(int process_id, + const HistogramSharedMemory::Config& config) { + auto region = UnsafeSharedMemoryRegion::Create(config.memory_size_bytes); + if (!region.IsValid()) { + DVLOG(1) << "Failed to create shared memory region."; + return absl::nullopt; + } + auto mapping = region.Map(); + if (!mapping.IsValid()) { + DVLOG(1) << "Failed to create shared memory mapping."; return absl::nullopt; } - auto shared_memory_mapping = shared_memory_region.Map(); - if (!shared_memory_mapping.IsValid()) { - return absl::nullopt; + return SharedMemory{std::move(region), + std::make_unique( + std::move(mapping), static_cast(process_id), + config.allocator_name)}; +} + +// static +bool HistogramSharedMemory::PassOnCommandLineIsEnabled( + std::string_view process_type) { + // On ChromeOS and for "utility" processes on other platforms there seems to + // be one or more mechanisms on startup which walk through all inherited + // shared memory regions and take a read-only handle to them. When we later + // attempt to deserialize the handle info and take a writable handle we + // find that the handle is already owned in read-only mode, triggering + // a crash due to "FD ownership violation". + // + // Example: The call to OpenSymbolFiles() in base/debug/stack_trace_posix.cc + // grabs a read-only handle to the shmem region for some process types. + // + // TODO(crbug.com/1028263): Fix ChromeOS and utility processes. + return (FeatureList::IsEnabled(kPassHistogramSharedMemoryOnLaunch) +#if BUILDFLAG(IS_CHROMEOS) + && process_type != "gpu-process" +#elif BUILDFLAG(IS_ANDROID) + && process_type != "utility" +#endif + ); +} + +// static +void HistogramSharedMemory::AddToLaunchParameters( + UnsafeSharedMemoryRegion histogram_shmem_region, +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) + GlobalDescriptors::Key descriptor_key, + ScopedFD& descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options) { + CHECK(command_line); + + const std::string process_type = command_line->GetSwitchValueASCII("type"); + const bool enabled = PassOnCommandLineIsEnabled(process_type); + + DVLOG(1) << (enabled ? "A" : "Not a") + << "dding histogram shared memory launch parameters for " + << process_type << " process."; + + if (!enabled) { + return; } - auto metrics_allocator = - std::make_unique( - std::move(shared_memory_mapping), - static_cast(unique_process_id), config.allocator_name); - - return HistogramSharedMemory{std::move(shared_memory_region), - std::move(metrics_allocator)}; + shared_memory::AddToLaunchParameters(::switches::kMetricsSharedMemoryHandle, + std::move(histogram_shmem_region), +#if BUILDFLAG(IS_APPLE) + kRendezvousKey, +#elif BUILDFLAG(IS_POSIX) + descriptor_key, descriptor_to_share, +#endif + command_line, launch_options); } -bool HistogramSharedMemory::IsValid() const { - return region_.IsValid() && allocator_ != nullptr; -} +// static +void HistogramSharedMemory::InitFromLaunchParameters( + const CommandLine& command_line) { + // TODO(crbug.com/1028263): Clean up once fully launched. + if (!command_line.HasSwitch(switches::kMetricsSharedMemoryHandle)) { + return; + } + CHECK(!GlobalHistogramAllocator::Get()); + DVLOG(1) << "Initializing histogram shared memory from command line for " + << command_line.GetSwitchValueASCII("type"); -base::WritableSharedMemoryRegion HistogramSharedMemory::TakeRegion() { - return std::move(region_); -} + auto shmem_region = shared_memory::UnsafeSharedMemoryRegionFrom( + command_line.GetSwitchValueASCII(switches::kMetricsSharedMemoryHandle)); -std::unique_ptr -HistogramSharedMemory::TakeAllocator() { - return std::move(allocator_); -} + SCOPED_CRASH_KEY_NUMBER( + "HistogramAllocator", "SharedMemError", + static_cast(shmem_region.has_value() + ? shared_memory::SharedMemoryError::kNoError + : shmem_region.error())); -HistogramSharedMemory::HistogramSharedMemory( - base::WritableSharedMemoryRegion region, - std::unique_ptr allocator) - : region_(std::move(region)), allocator_(std::move(allocator)) { - CHECK(IsValid()); + CHECK(shmem_region.has_value() && shmem_region.value().IsValid()) + << "Invald memory region passed on command line."; + + GlobalHistogramAllocator::CreateWithSharedMemoryRegion(shmem_region.value()); + + auto* global_allocator = GlobalHistogramAllocator::Get(); + CHECK(global_allocator); + global_allocator->CreateTrackingHistograms(global_allocator->Name()); } } // namespace base diff --git a/naiveproxy/src/base/metrics/histogram_shared_memory.h b/naiveproxy/src/base/metrics/histogram_shared_memory.h index d174492a1a..56b6089018 100644 --- a/naiveproxy/src/base/metrics/histogram_shared_memory.h +++ b/naiveproxy/src/base/metrics/histogram_shared_memory.h @@ -5,66 +5,112 @@ #ifndef BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ #define BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ +#include + #include "base/base_export.h" -#include "base/memory/writable_shared_memory_region.h" +#include "base/command_line.h" +#include "base/feature_list.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/metrics/persistent_memory_allocator.h" +#include "base/process/launch.h" +#include "build/build_config.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) +#include "base/files/platform_file.h" +#include "base/posix/global_descriptors.h" +#endif + +#if !BUILDFLAG(USE_BLINK) +#error "This is only intended for platforms that use blink." +#endif + namespace base { -// Configuration with which to create a histogram shared memory region and -// allocator. -struct BASE_EXPORT HistogramSharedMemoryConfig { - base::StringPiece allocator_name; - size_t memory_size_bytes; -}; +BASE_EXPORT BASE_DECLARE_FEATURE(kPassHistogramSharedMemoryOnLaunch); // Helper structure to create and return a shared memory region and a histogram // allocator over top of it. Once returned it is expected that the caller will // move both the memory regions and the allocator out of the struct and into // it's own appropriate state variables. Note that the memory region must // outlive the allocator. -class BASE_EXPORT HistogramSharedMemory { - public: - HistogramSharedMemory(); - ~HistogramSharedMemory(); +struct BASE_EXPORT HistogramSharedMemory { + HistogramSharedMemory() = delete; + ~HistogramSharedMemory() = delete; + HistogramSharedMemory(HistogramSharedMemory&) = delete; + HistogramSharedMemory(HistogramSharedMemory&&) = delete; + HistogramSharedMemory& operator=(HistogramSharedMemory&) = delete; + HistogramSharedMemory& operator=(HistogramSharedMemory&&) = delete; - // Move operations are supported. - HistogramSharedMemory(HistogramSharedMemory&& other); - HistogramSharedMemory& operator=(HistogramSharedMemory&& other); + // Configuration with which to create a histogram shared memory region and + // allocator. Note the expectation that this be initialized with static + // data for the allocator name (i.e., a string literal or static constant + // character array). + struct BASE_EXPORT Config { + const int process_type; // See: content/public/common/process_type.h + const std::string_view allocator_name; + const size_t memory_size_bytes; + }; - // Copy operations are NOT supported. - HistogramSharedMemory(const HistogramSharedMemory&) = delete; - HistogramSharedMemory& operator=(const HistogramSharedMemory&) = delete; + // Temporary structure used to return the shared memory region and allocator + // created by the |Create| factory function. The caller is expected to move + // the returned values out of this struct. + struct BASE_EXPORT SharedMemory { + UnsafeSharedMemoryRegion region; + std::unique_ptr allocator; - // Factory to initialize a shared memory region for |unique_process_id| - // based on |config|. - static absl::optional Create( - int unique_process_id, - const HistogramSharedMemoryConfig& config); + SharedMemory(UnsafeSharedMemoryRegion, + std::unique_ptr); + ~SharedMemory(); - // Returns true if the memory region and allocator are valid. - bool IsValid() const; + // Movable + SharedMemory(SharedMemory&&); + SharedMemory& operator=(SharedMemory&&); - // Returns, and transfers ownership of, the memory region to the caller. - base::WritableSharedMemoryRegion TakeRegion(); + // Not copyable + SharedMemory(SharedMemory&) = delete; + SharedMemory& operator=(SharedMemory&) = delete; + }; - // Returns, and transfers ownership of, the memory allocator to the caller. - std::unique_ptr - TakeAllocator(); + // Factory to initialize a shared |memory_region| and |allocator| for + // |process_id| based on |config|. On success, returns true and updates + // the values of |memory_region| and |allocator|. On failure, returns false + // and |memory_region| and |allocator| are unchanged. + static absl::optional Create(int process_id, + const Config& config); - private: - // Internal constructor. - HistogramSharedMemory( - base::WritableSharedMemoryRegion region, - std::unique_ptr allocator); +#if BUILDFLAG(IS_APPLE) + // Exposed for testing. + static const MachPortsForRendezvous::key_type kRendezvousKey; +#endif - // The shared memory region. - base::WritableSharedMemoryRegion region_; + // Returns true if passing the shared memory handle via command-line arguments + // is enabled. + static bool PassOnCommandLineIsEnabled(std::string_view process_type); - // The shared memory allocator. - std::unique_ptr allocator_; + // Updates the launch parameters to share |unsafe_memory_region| to a + // child process that is about to be launched. This should be called in the + // parent process as a part of setting up the launch conditions of the child. + // This call will update the |command_line| and |launch_options|. On posix, + // where we prefer to use a zygote instead of using the launch_options to + // launch a new process, the platform |descriptor_to_share| is returned. The + // caller is expected to transmit the descriptor to the launch flow for the + // zygote. + static void AddToLaunchParameters( + UnsafeSharedMemoryRegion unsafe_memory_region, +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE) + GlobalDescriptors::Key descriptor_key, + ScopedFD& descriptor_to_share, +#endif + CommandLine* command_line, + LaunchOptions* launch_options); + + // Initialize the (global) histogram shared memory from the launch parameters. + // This should be called in the child process before any histogram samples are + // recorded. + static void InitFromLaunchParameters(const CommandLine& command_line); }; } // namespace base + #endif // BASE_METRICS_HISTOGRAM_SHARED_MEMORY_H_ diff --git a/naiveproxy/src/base/metrics/metrics_hashes.cc b/naiveproxy/src/base/metrics/metrics_hashes.cc index 0632fd2a61..9843df9403 100644 --- a/naiveproxy/src/base/metrics/metrics_hashes.cc +++ b/naiveproxy/src/base/metrics/metrics_hashes.cc @@ -7,6 +7,7 @@ #include #include "base/check_op.h" +#include "base/containers/span.h" #include "base/hash/md5.h" #include "base/hash/sha1.h" #include "base/sys_byteorder.h" @@ -40,13 +41,13 @@ uint64_t HashMetricName(base::StringPiece name) { // struct.unpack('>Q', hashlib.md5(name.encode('utf-8')).digest()[:8])[0] // base::MD5Digest digest; - base::MD5Sum(name.data(), name.size(), &digest); + base::MD5Sum(base::as_byte_span(name), &digest); return DigestToUInt64(digest); } uint32_t HashMetricNameAs32Bits(base::StringPiece name) { base::MD5Digest digest; - base::MD5Sum(name.data(), name.size(), &digest); + base::MD5Sum(base::as_byte_span(name), &digest); return DigestToUInt32(digest); } diff --git a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc index e977452cc9..35b827f435 100644 --- a/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc +++ b/naiveproxy/src/base/metrics/persistent_histogram_allocator.cc @@ -16,9 +16,11 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/shared_memory_mapping.h" -#include "base/memory/writable_shared_memory_region.h" +#include "base/memory/unsafe_shared_memory_region.h" #include "base/metrics/histogram.h" #include "base/metrics/histogram_base.h" +#include "base/metrics/histogram_functions.h" +#include "base/metrics/histogram_macros.h" #include "base/metrics/histogram_samples.h" #include "base/metrics/metrics_hashes.h" #include "base/metrics/persistent_sample_map.h" @@ -933,14 +935,18 @@ bool GlobalHistogramAllocator::CreateSpareFile(const FilePath& spare_path, // static void GlobalHistogramAllocator::CreateWithSharedMemoryRegion( - const WritableSharedMemoryRegion& region) { + const UnsafeSharedMemoryRegion& region) { + CHECK_EQ(Get(), nullptr) << "Histogram allocator has already been created"; + base::WritableSharedMemoryMapping mapping = region.Map(); if (!mapping.IsValid() || !WritableSharedPersistentMemoryAllocator::IsSharedMemoryAcceptable( mapping)) { + DVLOG(1) << "Shared memory region is invalid or unacceptable."; return; } + DVLOG(1) << "Global histogram allocator initialized."; Set(new GlobalHistogramAllocator( std::make_unique( std::move(mapping), 0, StringPiece()))); @@ -954,10 +960,24 @@ void GlobalHistogramAllocator::Set(GlobalHistogramAllocator* allocator) { CHECK(!subtle::NoBarrier_Load(&g_histogram_allocator)); subtle::Release_Store(&g_histogram_allocator, reinterpret_cast(allocator)); - size_t existing = StatisticsRecorder::GetHistogramCount(); - DVLOG_IF(1, existing) - << existing << " histograms were created before persistence was enabled."; + // Record the number of histograms that were sampled before the global + // histogram allocator was initialized. + // + // TODO(crbug/1504919): CHECK(histogram_count == 0) and remove emit of early + // histogram count once |histogram_count| is reliably zero (0) for all process + // types. + size_t histogram_count = StatisticsRecorder::GetHistogramCount(); + if (histogram_count != 0) { + DVLOG(1) << histogram_count + << " histogram(s) created before persistence was enabled."; + + if (allocator && allocator->Name() && allocator->Name()[0]) { + UmaHistogramCounts100(StrCat({"UMA.PersistentAllocator.EarlyHistograms.", + allocator->Name()}), + static_cast(histogram_count)); + } + } } // static diff --git a/naiveproxy/src/base/metrics/persistent_histogram_allocator.h b/naiveproxy/src/base/metrics/persistent_histogram_allocator.h index d377b6fa28..a611ef5632 100644 --- a/naiveproxy/src/base/metrics/persistent_histogram_allocator.h +++ b/naiveproxy/src/base/metrics/persistent_histogram_allocator.h @@ -28,7 +28,7 @@ class BucketRanges; class FilePath; class PersistentSampleMapRecords; class PersistentSparseHistogramDataManager; -class WritableSharedMemoryRegion; +class UnsafeSharedMemoryRegion; // A data manager for sparse histograms so each instance of such doesn't have // to separately iterate over the entire memory segment. @@ -444,7 +444,7 @@ class BASE_EXPORT GlobalHistogramAllocator // current process's virtual address space and frees it upon destruction. // The memory will continue to live if other processes have access to it. static void CreateWithSharedMemoryRegion( - const WritableSharedMemoryRegion& region); + const UnsafeSharedMemoryRegion& region); // Sets a GlobalHistogramAllocator for globally storing histograms in // a space that can be persisted or shared between processes. There is only diff --git a/naiveproxy/src/base/metrics/persistent_memory_allocator.cc b/naiveproxy/src/base/metrics/persistent_memory_allocator.cc index ac6dcb8d2b..c73ecf48e8 100644 --- a/naiveproxy/src/base/metrics/persistent_memory_allocator.cc +++ b/naiveproxy/src/base/metrics/persistent_memory_allocator.cc @@ -400,8 +400,14 @@ PersistentMemoryAllocator::PersistentMemoryAllocator(Memory memory, shared_meta()->page_size = mem_page_; shared_meta()->version = kGlobalVersion; shared_meta()->id = id; - shared_meta()->freeptr.store(sizeof(SharedMetadata), - std::memory_order_release); + // Don't overwrite `freeptr` if it is set since we could have raced with + // another allocator. In such a case, `freeptr` would get "rewinded", and + // new objects would be allocated on top of already allocated objects. + uint32_t empty_freeptr = 0; + shared_meta()->freeptr.compare_exchange_strong( + /*expected=*/empty_freeptr, /*desired=*/sizeof(SharedMetadata), + /*success=*/std::memory_order_release, + /*failure=*/std::memory_order_relaxed); // Set up the queue of iterable allocations. shared_meta()->queue.size = sizeof(BlockHeader); @@ -827,9 +833,15 @@ void PersistentMemoryAllocator::MakeIterable(Reference ref) { volatile BlockHeader* block = GetBlock(ref, 0, 0, false, false); if (!block) // invalid reference return; - if (block->next.load(std::memory_order_acquire) != 0) // Already iterable. + + Reference empty_ref = 0; + if (!block->next.compare_exchange_strong( + /*expected=*/empty_ref, /*desired=*/kReferenceQueue, + /*success=*/std::memory_order_acq_rel, + /*failure=*/std::memory_order_acquire)) { + // Already iterable (or another thread is currently making this iterable). return; - block->next.store(kReferenceQueue, std::memory_order_release); // New tail. + } // Try to add this block to the tail of the queue. May take multiple tries. // If so, tail will be automatically updated with a more recent value during @@ -1245,7 +1257,7 @@ DelayedPersistentAllocation::DelayedPersistentAllocation( DelayedPersistentAllocation::~DelayedPersistentAllocation() = default; -void* DelayedPersistentAllocation::Get() const { +span DelayedPersistentAllocation::GetUntyped() const { // Relaxed operations are acceptable here because it's not protecting the // contents of the allocation in any way. Reference ref = reference_->load(std::memory_order_acquire); @@ -1259,8 +1271,9 @@ void* DelayedPersistentAllocation::Get() const { if (!ref) { ref = allocator_->Allocate(size_, type_); - if (!ref) - return nullptr; + if (!ref) { + return span(); + } // Store the new reference in its proper location using compare-and-swap. // Use a "strong" exchange to ensure no false-negatives since the operation @@ -1282,7 +1295,7 @@ void* DelayedPersistentAllocation::Get() const { } } - char* mem = allocator_->GetAsArray(ref, type_, size_); + uint8_t* mem = allocator_->GetAsArray(ref, type_, size_); if (!mem) { #if !BUILDFLAG(IS_NACL) // TODO(crbug/1432981): Remove these. They are used to investigate @@ -1291,6 +1304,17 @@ void* DelayedPersistentAllocation::Get() const { allocator_->IsFull()); SCOPED_CRASH_KEY_BOOL("PersistentMemoryAllocator", "corrupted", allocator_->IsCorrupt()); + SCOPED_CRASH_KEY_NUMBER("PersistentMemoryAllocator", "freeptr", + allocator_->freeptr()); + // The allocator's cookie should always be `kGlobalCookie`. Add it to crash + // keys to see if the file was corrupted externally, e.g. by a file + // shredder. Cast to volatile to avoid compiler optimizations and ensure + // that the actual value is read. + SCOPED_CRASH_KEY_NUMBER( + "PersistentMemoryAllocator", "cookie", + static_cast( + allocator_->shared_meta()) + ->cookie); SCOPED_CRASH_KEY_NUMBER("PersistentMemoryAllocator", "ref", ref); SCOPED_CRASH_KEY_BOOL("PersistentMemoryAllocator", "ref_found", ref_found); SCOPED_CRASH_KEY_BOOL("PersistentMemoryAllocator", "raced", raced); @@ -1315,15 +1339,15 @@ void* DelayedPersistentAllocation::Get() const { "PersistentMemoryAllocator", "ref_after", (reference_ + 1)->load(std::memory_order_relaxed)); DUMP_WILL_BE_NOTREACHED_NORETURN(); - return nullptr; + return span(); } #endif // !BUILDFLAG(IS_NACL) // This should never happen but be tolerant if it does as corruption from // the outside is something to guard against. DUMP_WILL_BE_NOTREACHED_NORETURN(); - return nullptr; + return span(); } - return mem + offset_; + return make_span(mem + offset_, size_ - offset_); } } // namespace base diff --git a/naiveproxy/src/base/metrics/persistent_memory_allocator.h b/naiveproxy/src/base/metrics/persistent_memory_allocator.h index 18401f9b81..22bd2102fe 100644 --- a/naiveproxy/src/base/metrics/persistent_memory_allocator.h +++ b/naiveproxy/src/base/metrics/persistent_memory_allocator.h @@ -15,6 +15,7 @@ #include "base/base_export.h" #include "base/check.h" #include "base/check_op.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" @@ -104,6 +105,18 @@ class BASE_EXPORT PersistentMemoryAllocator { public: typedef uint32_t Reference; + // All allocations and data-structures must be aligned to this byte boundary. + // Alignment as large as the physical bus between CPU and RAM is _required_ + // for some architectures, is simply more efficient on other CPUs, and + // generally a Good Idea(tm) for all platforms as it reduces/eliminates the + // chance that a type will span cache lines. Alignment mustn't be less + // than 8 to ensure proper alignment for all types. The rest is a balance + // between reducing spans across multiple cache lines and wasted space spent + // padding out allocations. An alignment of 16 would ensure that the block + // header structure always sits in a single cache line. An average of about + // 1/2 this value will be wasted with every allocation. + static constexpr size_t kAllocAlignment = 8; + // These states are used to indicate the overall condition of the memory // segment irrespective of what is stored within it. Because the data is // often persistent and thus needs to be readable by different versions of @@ -536,6 +549,7 @@ class BASE_EXPORT PersistentMemoryAllocator { // an "object" interface similar to new and delete. // Reserve space in the memory segment of the desired |size| and |type_id|. + // // A return value of zero indicates the allocation failed, otherwise the // returned reference can be used by any process to get a real pointer via // the GetAsObject() or GetAsArray calls. The actual allocated size may be @@ -550,6 +564,7 @@ class BASE_EXPORT PersistentMemoryAllocator { // when the last field is actually variable length. template T* New(size_t size) { + static_assert(alignof(T) <= kAllocAlignment); if (size < sizeof(T)) size = sizeof(T); Reference ref = Allocate(size, T::kPersistentTypeId); @@ -682,17 +697,6 @@ class BASE_EXPORT PersistentMemoryAllocator { private: struct SharedMetadata; struct BlockHeader; - // All allocations and data-structures must be aligned to this byte boundary. - // Alignment as large as the physical bus between CPU and RAM is _required_ - // for some architectures, is simply more efficient on other CPUs, and - // generally a Good Idea(tm) for all platforms as it reduces/eliminates the - // chance that a type will span cache lines. Alignment mustn't be less - // than 8 to ensure proper alignment for all types. The rest is a balance - // between reducing spans across multiple cache lines and wasted space spent - // padding out allocations. An alignment of 16 would ensure that the block - // header structure always sits in a single cache line. An average of about - // 1/2 this value will be wasted with every allocation. - static constexpr size_t kAllocAlignment = 8; static const Reference kReferenceQueue; // The shared metadata is always located at the top of the memory segment. @@ -756,7 +760,10 @@ class BASE_EXPORT PersistentMemoryAllocator { // Histogram recording errors. raw_ptr errors_histogram_ = nullptr; + // TODO(crbug.com/1432981) For debugging purposes. Remove these once done. + friend class DelayedPersistentAllocation; friend class metrics::FileMetricsProvider; + friend class PersistentMemoryAllocatorTest; FRIEND_TEST_ALL_PREFIXES(PersistentMemoryAllocatorTest, AllocateAndIterate); }; @@ -924,15 +931,26 @@ class BASE_EXPORT DelayedPersistentAllocation { size_t offset = 0); ~DelayedPersistentAllocation(); - // Gets a pointer to the defined allocation. This will realize the request + // Gets a span to the defined allocation. This will realize the request // and update the reference provided during construction. The memory will // be zeroed the first time it is returned, after that it is shared with // all other Get() requests and so shows any changes made to it elsewhere. // - // If the allocation fails for any reason, null will be returned. This works - // even on "const" objects because the allocation is already defined, just - // delayed. - void* Get() const; + // If the allocation fails for any reason, an empty span will be returned. + // This works even on "const" objects because the allocation is already + // defined, just delayed. + template + span Get() const { + // PersistentMemoryAllocator only supports types with alignment at most + // kAllocAlignment. + static_assert(alignof(T) <= PersistentMemoryAllocator::kAllocAlignment); + // The offset must be a multiple of the alignment or misaligned pointers + // will result. + CHECK_EQ(offset_ % alignof(T), 0u); + span untyped = GetUntyped(); + return make_span(reinterpret_cast(untyped.data()), + untyped.size() / sizeof(T)); + } // Gets the internal reference value. If this returns a non-zero value then // a subsequent call to Get() will do nothing but convert that reference into @@ -943,6 +961,8 @@ class BASE_EXPORT DelayedPersistentAllocation { } private: + span GetUntyped() const; + // The underlying object that does the actual allocation of memory. Its // lifetime must exceed that of all DelayedPersistentAllocation objects // that use it. diff --git a/naiveproxy/src/base/metrics/sample_vector.cc b/naiveproxy/src/base/metrics/sample_vector.cc index 8c45ddbccb..7f31bf7730 100644 --- a/naiveproxy/src/base/metrics/sample_vector.cc +++ b/naiveproxy/src/base/metrics/sample_vector.cc @@ -8,6 +8,7 @@ #include "base/check_op.h" #include "base/compiler_specific.h" +#include "base/containers/heap_array.h" #include "base/debug/crash_logging.h" #include "base/lazy_instance.h" #include "base/memory/ptr_util.h" @@ -15,6 +16,8 @@ #include "base/metrics/persistent_memory_allocator.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" @@ -38,7 +41,6 @@ class IteratorTemplate : public SampleCountIterator { public: IteratorTemplate(base::span counts, const BucketRanges* bucket_ranges) : counts_(counts), bucket_ranges_(bucket_ranges) { - DCHECK_GE(bucket_ranges_->bucket_count(), counts_.size()); SkipEmptyBuckets(); } @@ -125,15 +127,19 @@ void ExtractingSampleVectorIterator::Get(HistogramBase::Sample* min, SampleVectorBase::SampleVectorBase(uint64_t id, Metadata* meta, const BucketRanges* bucket_ranges) - : HistogramSamples(id, meta), bucket_ranges_(bucket_ranges) { - CHECK_GE(bucket_ranges_->bucket_count(), 1u); + : HistogramSamples(id, meta), + bucket_ranges_(bucket_ranges), + counts_size_(bucket_ranges_->bucket_count()) { + CHECK_GE(counts_size_, 1u); } SampleVectorBase::SampleVectorBase(uint64_t id, std::unique_ptr meta, const BucketRanges* bucket_ranges) - : HistogramSamples(id, std::move(meta)), bucket_ranges_(bucket_ranges) { - CHECK_GE(bucket_ranges_->bucket_count(), 1u); + : HistogramSamples(id, std::move(meta)), + bucket_ranges_(bucket_ranges), + counts_size_(bucket_ranges_->bucket_count()) { + CHECK_GE(counts_size_, 1u); } SampleVectorBase::~SampleVectorBase() = default; @@ -142,7 +148,7 @@ void SampleVectorBase::Accumulate(Sample value, Count count) { const size_t bucket_index = GetBucketIndex(value); // Handle the single-sample case. - if (!counts()) { + if (!counts().has_value()) { // Try to accumulate the parameters into the single-count entry. if (AccumulateSingleSample(value, count, bucket_index)) { // A race condition could lead to a new single-sample being accumulated @@ -150,8 +156,9 @@ void SampleVectorBase::Accumulate(Sample value, Count count) { // Since it is mounted, it could be mounted elsewhere and have values // written to it. It's not allowed to have both a single-sample and // entries in the counts array so move the single-sample. - if (counts()) + if (counts().has_value()) { MoveSingleSampleToCounts(); + } return; } @@ -162,7 +169,7 @@ void SampleVectorBase::Accumulate(Sample value, Count count) { // Handle the multi-sample case. Count new_bucket_count = - subtle::NoBarrier_AtomicIncrement(&counts()[bucket_index], count); + subtle::NoBarrier_AtomicIncrement(&counts_at(bucket_index), count); IncreaseSumAndCount(strict_cast(count) * value, count); // TODO(bcwhite) Remove after crbug.com/682680. @@ -181,16 +188,18 @@ Count SampleVectorBase::GetCount(Sample value) const { Count SampleVectorBase::TotalCount() const { // Handle the single-sample case. SingleSample sample = single_sample().Load(); - if (sample.count != 0) + if (sample.count != 0) { return sample.count; + } // Handle the multi-sample case. - if (counts() || MountExistingCountsStorage()) { + if (counts().has_value() || MountExistingCountsStorage()) { Count count = 0; - size_t size = counts_size(); - const HistogramBase::AtomicCount* counts_array = counts(); - for (size_t i = 0; i < size; ++i) { - count += subtle::NoBarrier_Load(&counts_array[i]); + // TODO(danakj): In C++23 we can skip the `counts_span` lvalue and iterate + // over `counts().value()` directly without creating a dangling reference. + span counts_span = counts().value(); + for (const HistogramBase::AtomicCount& c : counts_span) { + count += subtle::NoBarrier_Load(&c); } return count; } @@ -204,12 +213,14 @@ Count SampleVectorBase::GetCountAtIndex(size_t bucket_index) const { // Handle the single-sample case. SingleSample sample = single_sample().Load(); - if (sample.count != 0) + if (sample.count != 0) { return sample.bucket == bucket_index ? sample.count : 0; + } // Handle the multi-sample case. - if (counts() || MountExistingCountsStorage()) - return subtle::NoBarrier_Load(&counts()[bucket_index]); + if (counts().has_value() || MountExistingCountsStorage()) { + return subtle::NoBarrier_Load(&counts_at(bucket_index)); + } // And the no-value case. return 0; @@ -226,9 +237,8 @@ std::unique_ptr SampleVectorBase::Iterator() const { } // Handle the multi-sample case. - if (counts() || MountExistingCountsStorage()) { - return std::make_unique( - base::make_span(counts(), counts_size()), bucket_ranges_); + if (counts().has_value() || MountExistingCountsStorage()) { + return std::make_unique(*counts(), bucket_ranges_); } // And the no-value case. @@ -256,9 +266,9 @@ std::unique_ptr SampleVectorBase::ExtractingIterator() { } // Handle the multi-sample case. - if (counts() || MountExistingCountsStorage()) { - return std::make_unique( - base::make_span(counts(), counts_size()), bucket_ranges_); + if (counts().has_value() || MountExistingCountsStorage()) { + return std::make_unique(*counts(), + bucket_ranges_); } // And the no-value case. @@ -269,8 +279,9 @@ std::unique_ptr SampleVectorBase::ExtractingIterator() { bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, HistogramSamples::Operator op) { // Stop now if there's nothing to do. - if (iter->Done()) + if (iter->Done()) { return true; + } // Get the first value and its index. HistogramBase::Sample min; @@ -291,10 +302,12 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, // is why it's necessary to initialize it to something. size_t index_offset = 0; size_t iter_index; - if (iter->GetBucketIndex(&iter_index)) + if (iter->GetBucketIndex(&iter_index)) { index_offset = dest_index - iter_index; - if (dest_index >= counts_size()) + } + if (dest_index >= counts_size()) { return false; + } // Post-increment. Information about the current sample is not available // after this point. @@ -302,7 +315,7 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, // Single-value storage is possible if there is no counts storage and the // retrieved entry is the only one in the iterator. - if (!counts()) { + if (!counts().has_value()) { if (iter->Done()) { // Don't call AccumulateSingleSample because that updates sum and count // which was already done by the caller of this method. @@ -310,8 +323,9 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, dest_index, op == HistogramSamples::ADD ? count : -count)) { // Handle race-condition that mounted counts storage between above and // here. - if (counts()) + if (counts().has_value()) { MoveSingleSampleToCounts(); + } return true; } } @@ -343,12 +357,13 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, // Sample's bucket matches exactly. Adjust count. subtle::NoBarrier_AtomicIncrement( - &counts()[dest_index], op == HistogramSamples::ADD ? count : -count); + &counts_at(dest_index), op == HistogramSamples::ADD ? count : -count); // Advance to the next iterable sample. See comments above for how // everything works. - if (iter->Done()) + if (iter->Done()) { return true; + } iter->Get(&min, &max, &count); if (iter->GetBucketIndex(&iter_index)) { // Destination bucket is a known offset from the source bucket. @@ -357,8 +372,9 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, // Destination bucket has to be determined anew each time. dest_index = GetBucketIndex(min); } - if (dest_index >= counts_size()) + if (dest_index >= counts_size()) { return false; + } iter->Next(); } } @@ -368,7 +384,6 @@ bool SampleVectorBase::AddSubtractImpl(SampleCountIterator* iter, // knew that the buckets were linearly distributed. size_t SampleVectorBase::GetBucketIndex(Sample value) const { size_t bucket_count = bucket_ranges_->bucket_count(); - CHECK_GE(bucket_count, 1u); CHECK_GE(value, bucket_ranges_->range(0)); CHECK_LT(value, bucket_ranges_->range(bucket_count)); @@ -378,11 +393,13 @@ size_t SampleVectorBase::GetBucketIndex(Sample value) const { Sample maximum = bucket_ranges_->range(bucket_count - 1); if (maximum == static_cast(bucket_count - 1)) { // |value| is in the underflow bucket. - if (value < 1) + if (value < 1) { return 0; + } // |value| is in the overflow bucket. - if (value > maximum) + if (value > maximum) { return bucket_count - 1; + } return static_cast(value); } @@ -391,13 +408,15 @@ size_t SampleVectorBase::GetBucketIndex(Sample value) const { size_t mid; do { DCHECK_GE(over, under); - mid = under + (over - under)/2; - if (mid == under) + mid = under + (over - under) / 2; + if (mid == under) { break; - if (bucket_ranges_->range(mid) <= value) + } + if (bucket_ranges_->range(mid) <= value) { under = mid; - else + } else { over = mid; + } } while (true); DCHECK_LE(bucket_ranges_->range(mid), value); @@ -406,15 +425,16 @@ size_t SampleVectorBase::GetBucketIndex(Sample value) const { } void SampleVectorBase::MoveSingleSampleToCounts() { - DCHECK(counts()); + DCHECK(counts().has_value()); // Disable the single-sample since there is now counts storage for the data. SingleSample sample = single_sample().ExtractAndDisable(); // Stop here if there is no "count" as trying to find the bucket index of // an invalid (including zero) "value" will crash. - if (sample.count == 0) + if (sample.count == 0) { return; + } // Stop here if the sample bucket would be out of range for the AtomicCount // array. @@ -424,24 +444,22 @@ void SampleVectorBase::MoveSingleSampleToCounts() { // Move the value into storage. Sum and redundant-count already account // for this entry so no need to call IncreaseSumAndCount(). - subtle::NoBarrier_AtomicIncrement(&counts()[sample.bucket], sample.count); + subtle::NoBarrier_AtomicIncrement(&counts_at(sample.bucket), sample.count); } void SampleVectorBase::MountCountsStorageAndMoveSingleSample() { // There are many SampleVector objects and the lock is needed very // infrequently (just when advancing from single-sample to multi-sample) so // define a single, global lock that all can use. This lock only prevents - // concurrent entry into the code below; access and updates to |counts_| + // concurrent entry into the code below; access and updates to |counts_data_| // still requires atomic operations. static LazyInstance::Leaky counts_lock = LAZY_INSTANCE_INITIALIZER; - if (!counts_.load(std::memory_order_relaxed)) { + if (counts_data_.load(std::memory_order_relaxed) == nullptr) { AutoLock lock(counts_lock.Get()); - if (!counts_.load(std::memory_order_relaxed)) { + if (counts_data_.load(std::memory_order_relaxed) == nullptr) { // Create the actual counts storage while the above lock is acquired. - HistogramBase::Count* counts = CreateCountsStorageWhileLocked(); - DCHECK(counts); - - // Point |counts_| to the newly created storage. This is done while + span counts = CreateCountsStorageWhileLocked(); + // Point |counts()| to the newly created storage. This is done while // locked to prevent possible concurrent calls to CreateCountsStorage // but, between that call and here, other threads could notice the // existence of the storage and race with this to set_counts(). That's @@ -476,24 +494,24 @@ bool SampleVector::IsDefinitelyEmpty() const { bool SampleVector::MountExistingCountsStorage() const { // There is never any existing storage other than what is already in use. - return counts() != nullptr; + return counts().has_value(); } std::string SampleVector::GetAsciiHeader(StringPiece histogram_name, int32_t flags) const { Count sample_count = TotalCount(); std::string output; - StringAppendF(&output, "Histogram: %.*s recorded %d samples", - static_cast(histogram_name.size()), histogram_name.data(), - sample_count); + StrAppend(&output, {"Histogram: ", histogram_name, " recorded ", + NumberToString(sample_count), " samples"}); if (sample_count == 0) { DCHECK_EQ(sum(), 0); } else { double mean = static_cast(sum()) / sample_count; StringAppendF(&output, ", mean = %.1f", mean); } - if (flags) + if (flags) { StringAppendF(&output, " (flags = 0x%x)", flags); + } return output; } @@ -507,8 +525,9 @@ std::string SampleVector::GetAsciiBody() const { // Scale histogram bucket counts to take at most 72 characters. // Note: Keep in sync w/ kLineLength histogram_samples.cc const double kLineLength = 72; - if (max_size > kLineLength) + if (max_size > kLineLength) { scaling_factor = kLineLength / max_size; + } // Calculate largest print width needed for any of our bucket range displays. size_t print_width = 1; @@ -516,8 +535,9 @@ std::string SampleVector::GetAsciiBody() const { if (GetCountAtIndex(i)) { size_t width = GetSimpleAsciiBucketRange(bucket_ranges()->range(i)).size() + 1; - if (width > print_width) + if (width > print_width) { print_width = width; + } } } @@ -530,8 +550,9 @@ std::string SampleVector::GetAsciiBody() const { remaining -= current; std::string range = GetSimpleAsciiBucketRange(bucket_ranges()->range(i)); output.append(range); - for (size_t j = 0; range.size() + j < print_width + 1; ++j) + for (size_t j = 0; range.size() + j < print_width + 1; ++j) { output.push_back(' '); + } if (0 == current && i < bucket_count() - 1 && 0 == GetCountAtIndex(i + 1)) { while (i < bucket_count() - 1 && 0 == GetCountAtIndex(i + 1)) { ++i; @@ -553,8 +574,9 @@ double SampleVector::GetPeakBucketSize() const { Count max = 0; for (uint32_t i = 0; i < bucket_count(); ++i) { Count current = GetCountAtIndex(i); - if (current > max) + if (current > max) { max = current; + } } return max; } @@ -572,9 +594,10 @@ void SampleVector::WriteAsciiBucketContext(int64_t past, } } -HistogramBase::AtomicCount* SampleVector::CreateCountsStorageWhileLocked() { +span +SampleVector::CreateCountsStorageWhileLocked() { local_counts_.resize(counts_size()); - return &local_counts_[0]; + return local_counts_; } PersistentSampleVector::PersistentSampleVector( @@ -617,32 +640,44 @@ bool PersistentSampleVector::MountExistingCountsStorage() const { // There is no early exit if counts is not yet mounted because, given that // this is a virtual function, it's more efficient to do that at the call- // site. There is no danger, however, should this get called anyway (perhaps - // because of a race condition) because at worst the |counts_| value would - // be over-written (in an atomic manner) with the exact same address. + // because of a race condition) because at worst the `counts_data_` and + // `counts_size_` members would be over-written (in an atomic manner) + // with the exact same values. - if (!persistent_counts_.reference()) + if (!persistent_counts_.reference()) { return false; // Nothing to mount. - - // Mount the counts array in position. - set_counts( - static_cast(persistent_counts_.Get())); - - // The above shouldn't fail but can if the data is corrupt or incomplete. - return counts() != nullptr; -} - -HistogramBase::AtomicCount* -PersistentSampleVector::CreateCountsStorageWhileLocked() { - void* mem = persistent_counts_.Get(); - if (!mem) { - // The above shouldn't fail but can if Bad Things(tm) are occurring in the - // persistent allocator. Crashing isn't a good option so instead just - // allocate something from the heap and return that. There will be no - // sharing or persistence but worse things are already happening. - return new HistogramBase::AtomicCount[counts_size()]; } - return static_cast(mem); + // Mount the counts array in position. This shouldn't fail but can if the + // data is corrupt or incomplete. + span mem = + persistent_counts_.Get(); + if (mem.empty()) { + return false; + } + // Uses a span that only covers the counts the SampleVector should have + // access to, which can be a subset of the entire persistent allocation. + set_counts(mem.first(counts_size())); + return true; +} + +span +PersistentSampleVector::CreateCountsStorageWhileLocked() { + span mem = + persistent_counts_.Get(); + if (mem.empty()) { + // The above shouldn't fail but can if Bad Things(tm) are occurring in + // the persistent allocator. Crashing isn't a good option so instead + // just allocate something from the heap that we will leak and return that. + // There will be no sharing or persistence but worse things are already + // happening. + auto array = HeapArray::WithSize(counts_size()); + return std::move(array).leak(); + } + + // Returns a span that only covers the counts the SampleVector should have + // access to, which can be a subset of the entire persistent allocation. + return mem.first(counts_size()); } } // namespace base diff --git a/naiveproxy/src/base/metrics/sample_vector.h b/naiveproxy/src/base/metrics/sample_vector.h index b1059ec4b8..b37f7d14d1 100644 --- a/naiveproxy/src/base/metrics/sample_vector.h +++ b/naiveproxy/src/base/metrics/sample_vector.h @@ -18,6 +18,7 @@ #include "base/base_export.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/metrics/bucket_ranges.h" @@ -75,45 +76,76 @@ class BASE_EXPORT SampleVectorBase : public HistogramSamples { // "const" restriction that is often used to indicate read-only memory. virtual bool MountExistingCountsStorage() const = 0; - // Creates "counts" storage and returns a pointer to it. Ownership of the + // Creates "counts" storage and returns a span to it. The span's size must + // be the number of counts required by the histogram. Ownership of the // array remains with the called method but will never change. This must be // called while some sort of lock is held to prevent reentry. - virtual HistogramBase::Count* CreateCountsStorageWhileLocked() = 0; + virtual span CreateCountsStorageWhileLocked() = 0; - HistogramBase::AtomicCount* counts() { - return counts_.load(std::memory_order_acquire); + std::optional> counts() { + HistogramBase::AtomicCount* data = + counts_data_.load(std::memory_order_acquire); + if (data == nullptr) { + return std::nullopt; + } + return std::make_optional(make_span(data, counts_size_)); } - const HistogramBase::AtomicCount* counts() const { - return counts_.load(std::memory_order_acquire); + std::optional> counts() const { + const HistogramBase::AtomicCount* data = + counts_data_.load(std::memory_order_acquire); + if (data == nullptr) { + return std::nullopt; + } + return std::make_optional(make_span(data, counts_size_)); } - void set_counts(HistogramBase::AtomicCount* counts) const { - counts_.store(counts, std::memory_order_release); + void set_counts(span counts) const { + CHECK_EQ(counts.size(), counts_size_); + counts_data_.store(counts.data(), std::memory_order_release); } - size_t counts_size() const { return bucket_ranges_->bucket_count(); } + size_t counts_size() const { return counts_size_; } private: friend class SampleVectorTest; FRIEND_TEST_ALL_PREFIXES(HistogramTest, CorruptSampleCounts); FRIEND_TEST_ALL_PREFIXES(SharedHistogramTest, CorruptSampleCounts); - // |counts_| is actually a pointer to a HistogramBase::AtomicCount array but - // is held as an atomic pointer for concurrency reasons. When combined with - // the single_sample held in the metadata, there are four possible states: + // Returns a reference into the `counts()` array. As `counts()` may be an + // empty optional until the array is populated, `counts()` must be checked for + // having a value before calling `counts_at()`, or this method may CHECK-fail. + const HistogramBase::AtomicCount& counts_at(size_t index) const { + return (counts().value())[index]; + } + HistogramBase::AtomicCount& counts_at(size_t index) { + return (counts().value())[index]; + } + + // Shares the same BucketRanges with Histogram object. + const raw_ptr bucket_ranges_; + + // The number of counts in the histogram. Once `counts_data_` becomes + // non-null, this is the number of values in the `counts_data_` array that + // are usable by the SampleVector. + const size_t counts_size_; + + // `counts_data_` is a pointer to a `HistogramBase::AtomicCount` array that is + // held as an atomic pointer for concurrency reasons. When combined with the + // single_sample held in the metadata, there are four possible states: // 1) single_sample == zero, counts_ == null // 2) single_sample != zero, counts_ == null // 3) single_sample != zero, counts_ != null BUT IS EMPTY // 4) single_sample == zero, counts_ != null and may have data - // Once |counts_| is set, it can never revert and any existing single-sample - // must be moved to this storage. It is mutable because changing it doesn't - // change the (const) data but must adapt if a non-const object causes the - // storage to be allocated and updated. - mutable std::atomic counts_{nullptr}; - - // Shares the same BucketRanges with Histogram object. - const raw_ptr bucket_ranges_; + // Once `counts_data_` is set to a value, it can never be changed and any + // existing single-sample must be moved to this storage. It is mutable because + // changing it doesn't change the (const) data but must adapt if a non-const + // object causes the storage to be allocated and updated. + // + // Held as raw pointer in atomic, instead of as a span, to avoid locks. The + // `counts_size_` is the size of the would-be span, which is CHECKd when + // setting the pointer, and used to recreate a span on the way out. + mutable std::atomic counts_data_; }; // A sample vector that uses local memory for the counts array. @@ -138,7 +170,7 @@ class BASE_EXPORT SampleVector : public SampleVectorBase { // SampleVectorBase: bool MountExistingCountsStorage() const override; - HistogramBase::Count* CreateCountsStorageWhileLocked() override; + span CreateCountsStorageWhileLocked() override; // Writes cumulative percentage information based on the number // of past, current, and remaining bucket samples. @@ -174,7 +206,7 @@ class BASE_EXPORT PersistentSampleVector : public SampleVectorBase { private: // SampleVectorBase: bool MountExistingCountsStorage() const override; - HistogramBase::Count* CreateCountsStorageWhileLocked() override; + span CreateCountsStorageWhileLocked() override; // Persistent storage for counts. DelayedPersistentAllocation persistent_counts_; diff --git a/naiveproxy/src/base/metrics/statistics_recorder.cc b/naiveproxy/src/base/metrics/statistics_recorder.cc index 44d7a51c18..19f2b7fe06 100644 --- a/naiveproxy/src/base/metrics/statistics_recorder.cc +++ b/naiveproxy/src/base/metrics/statistics_recorder.cc @@ -105,10 +105,13 @@ void StatisticsRecorder::RegisterHistogramProvider( // static HistogramBase* StatisticsRecorder::RegisterOrDeleteDuplicate( HistogramBase* histogram) { + CHECK(histogram); + uint64_t hash = histogram->name_hash(); // Ensure that histograms use HashMetricName() to compute their hash, since - // that function is used to look up histograms. + // that function is used to look up histograms. Intentionally a DCHECK since + // this is expensive. DCHECK_EQ(hash, HashMetricName(histogram->histogram_name())); // Declared before |auto_lock| so that the histogram is deleted after the lock @@ -378,7 +381,7 @@ void StatisticsRecorder::RemoveHistogramSampleObserver( EnsureGlobalRecorderWhileLocked(); auto iter = top_->observers_.find(hash); - DCHECK(iter != top_->observers_.end()); + CHECK(iter != top_->observers_.end(), base::NotFatalUntil::M125); auto result = iter->second->RemoveObserver(observer); if (result == diff --git a/naiveproxy/src/base/native_library_ios.mm b/naiveproxy/src/base/native_library_ios.mm index 109d39ea5e..34350f2d8f 100644 --- a/naiveproxy/src/base/native_library_ios.mm +++ b/naiveproxy/src/base/native_library_ios.mm @@ -5,7 +5,7 @@ #include "base/native_library.h" #include "base/check.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" diff --git a/naiveproxy/src/base/notimplemented.h b/naiveproxy/src/base/notimplemented.h new file mode 100644 index 0000000000..c3415fcbfb --- /dev/null +++ b/naiveproxy/src/base/notimplemented.h @@ -0,0 +1,34 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NOTIMPLEMENTED_H_ +#define BASE_NOTIMPLEMENTED_H_ + +#include "base/check.h" +#include "base/dcheck_is_on.h" + +// The NOTIMPLEMENTED() macro annotates codepaths which have not been +// implemented yet. If output spam is a serious concern, +// NOTIMPLEMENTED_LOG_ONCE() can be used. +#if DCHECK_IS_ON() +#define NOTIMPLEMENTED() \ + ::logging::CheckError::NotImplemented(__PRETTY_FUNCTION__) + +// The lambda returns false the first time it is run, and true every other time. +#define NOTIMPLEMENTED_LOG_ONCE() \ + LOGGING_CHECK_FUNCTION_IMPL(NOTIMPLEMENTED(), []() { \ + bool old_value = true; \ + [[maybe_unused]] static const bool call_once = [](bool* b) { \ + *b = false; \ + return true; \ + }(&old_value); \ + return old_value; \ + }()) + +#else +#define NOTIMPLEMENTED() EAT_CHECK_STREAM_PARAMS() +#define NOTIMPLEMENTED_LOG_ONCE() EAT_CHECK_STREAM_PARAMS() +#endif + +#endif // BASE_NOTIMPLEMENTED_H_ diff --git a/naiveproxy/src/base/notreached.h b/naiveproxy/src/base/notreached.h index 55227c1601..199f066f8a 100644 --- a/naiveproxy/src/base/notreached.h +++ b/naiveproxy/src/base/notreached.h @@ -10,6 +10,10 @@ #include "base/dcheck_is_on.h" #include "base/logging_buildflags.h" +// TODO(crbug.com/1520664): Remove once NOTIMPLEMENTED() call sites include +// base/notimplemented.h. +#include "base/notimplemented.h" + namespace logging { // NOTREACHED() annotates should-be unreachable code. When a base::NotFatalUntil @@ -63,29 +67,6 @@ namespace logging { #define DUMP_WILL_BE_NOTREACHED_NORETURN() \ ::logging::CheckError::DumpWillBeNotReachedNoreturn() -// The NOTIMPLEMENTED() macro annotates codepaths which have not been -// implemented yet. If output spam is a serious concern, -// NOTIMPLEMENTED_LOG_ONCE() can be used. -#if DCHECK_IS_ON() -#define NOTIMPLEMENTED() \ - ::logging::CheckError::NotImplemented(__PRETTY_FUNCTION__) - -// The lambda returns false the first time it is run, and true every other time. -#define NOTIMPLEMENTED_LOG_ONCE() \ - LOGGING_CHECK_FUNCTION_IMPL(NOTIMPLEMENTED(), []() { \ - bool old_value = true; \ - [[maybe_unused]] static const bool call_once = [](bool* b) { \ - *b = false; \ - return true; \ - }(&old_value); \ - return old_value; \ - }()) - -#else -#define NOTIMPLEMENTED() EAT_CHECK_STREAM_PARAMS() -#define NOTIMPLEMENTED_LOG_ONCE() EAT_CHECK_STREAM_PARAMS() -#endif - } // namespace logging #endif // BASE_NOTREACHED_H_ diff --git a/naiveproxy/src/base/numerics/BUILD.gn b/naiveproxy/src/base/numerics/BUILD.gn index e6f221537c..7b305b390d 100644 --- a/naiveproxy/src/base/numerics/BUILD.gn +++ b/naiveproxy/src/base/numerics/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright 2017 The Chromium Authors +# Copyright 2024 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -9,6 +9,7 @@ source_set("base_numerics") { visibility = [ "//base/*" ] sources = [ + "basic_ops_impl.h", "checked_math_impl.h", "clamped_math_impl.h", "safe_conversions_arm_impl.h", @@ -18,6 +19,7 @@ source_set("base_numerics") { "safe_math_shared_impl.h", ] public = [ + "byte_conversions.h", "checked_math.h", "clamped_math.h", "math_constants.h", diff --git a/naiveproxy/src/base/numerics/basic_ops_impl.h b/naiveproxy/src/base/numerics/basic_ops_impl.h new file mode 100644 index 0000000000..12461c8fa7 --- /dev/null +++ b/naiveproxy/src/base/numerics/basic_ops_impl.h @@ -0,0 +1,135 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_BASIC_OPS_IMPL_H_ +#define BASE_NUMERICS_BASIC_OPS_IMPL_H_ + +#include +#include +#include +#include +#include +#include + +namespace base::numerics::internal { + +// The correct type to perform math operations on given values of type `T`. This +// may be a larger type than `T` to avoid promotion to `int` which involves sign +// conversion! +template + requires(std::is_integral_v) +using MathType = std::conditional_t< + sizeof(T) >= sizeof(int), + T, + std::conditional_t, int, unsigned int>>; + +// Reverses the byte order of the integer. +template + requires(std::is_unsigned_v && std::is_integral_v) +inline constexpr T SwapBytes(T value) { + // MSVC intrinsics are not constexpr, so we provide our own constexpr + // implementation. We provide it unconditionally so we can test it on all + // platforms for correctness. + if (std::is_constant_evaluated()) { + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == 2u) { + MathType a = (MathType(value) >> 0) & MathType{0xff}; + MathType b = (MathType(value) >> 8) & MathType{0xff}; + return static_cast((a << 8) | (b << 0)); + } else if constexpr (sizeof(T) == 4u) { + T a = (value >> 0) & T{0xff}; + T b = (value >> 8) & T{0xff}; + T c = (value >> 16) & T{0xff}; + T d = (value >> 24) & T{0xff}; + return (a << 24) | (b << 16) | (c << 8) | (d << 0); + } else { + static_assert(sizeof(T) == 8u); + T a = (value >> 0) & T{0xff}; + T b = (value >> 8) & T{0xff}; + T c = (value >> 16) & T{0xff}; + T d = (value >> 24) & T{0xff}; + T e = (value >> 32) & T{0xff}; + T f = (value >> 40) & T{0xff}; + T g = (value >> 48) & T{0xff}; + T h = (value >> 56) & T{0xff}; + return (a << 56) | (b << 48) | (c << 40) | (d << 32) | // + (e << 24) | (f << 16) | (g << 8) | (h << 0); + } + } + +#if _MSC_VER + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == sizeof(unsigned short)) { + using U = unsigned short; + return _byteswap_ushort(U{value}); + } else if constexpr (sizeof(T) == sizeof(unsigned long)) { + using U = unsigned long; + return _byteswap_ulong(U{value}); + } else { + static_assert(sizeof(T) == 8u); + return _byteswap_uint64(value); + } +#else + if constexpr (sizeof(T) == 1u) { + return value; + } else if constexpr (sizeof(T) == 2u) { + return __builtin_bswap16(uint16_t{value}); + } else if constexpr (sizeof(T) == 4u) { + return __builtin_bswap32(value); + } else { + static_assert(sizeof(T) == 8u); + return __builtin_bswap64(value); + } +#endif +} + +// Converts from a byte array to an integer. +template + requires(std::is_unsigned_v && std::is_integral_v) +inline constexpr T FromLittleEndian(std::span bytes) { + T val; + if (std::is_constant_evaluated()) { + val = T{0}; + for (size_t i = 0u; i < sizeof(T); i += 1u) { + // SAFETY: `i < sizeof(T)` (the number of bytes in T), so `(8 * i)` is + // less than the number of bits in T. + val |= MathType(bytes[i]) << (8u * i); + } + } else { + // SAFETY: `bytes` has sizeof(T) bytes, and `val` is of type `T` so has + // sizeof(T) bytes, and the two can not alias as `val` is a stack variable. + memcpy(&val, bytes.data(), sizeof(T)); + } + return val; +} + +// Converts to a byte array from an integer. +template + requires(std::is_unsigned_v && std::is_integral_v) +inline constexpr std::array ToLittleEndian(T val) { + auto bytes = std::array(); + if (std::is_constant_evaluated()) { + for (size_t i = 0u; i < sizeof(T); i += 1u) { + const auto last_byte = static_cast(val & 0xff); + // The low bytes go to the front of the array in little endian. + bytes[i] = last_byte; + // If `val` is one byte, this shift would be UB. But it's also not needed + // since the loop will not run again. + if constexpr (sizeof(T) > 1u) { + val >>= 8u; + } + } + } else { + // SAFETY: `bytes` has sizeof(T) bytes, and `val` is of type `T` so has + // sizeof(T) bytes, and the two can not alias as `val` is a stack variable. + memcpy(bytes.data(), &val, sizeof(T)); + } + return bytes; +} + +} // namespace base::numerics::internal + +#endif // BASE_NUMERICS_BASIC_OPS_IMPL_H_ diff --git a/naiveproxy/src/base/numerics/byte_conversions.h b/naiveproxy/src/base/numerics/byte_conversions.h new file mode 100644 index 0000000000..53ee738a33 --- /dev/null +++ b/naiveproxy/src/base/numerics/byte_conversions.h @@ -0,0 +1,437 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_NUMERICS_BYTE_CONVERSIONS_H_ +#define BASE_NUMERICS_BYTE_CONVERSIONS_H_ + +#include +#include +#include +#include +#include + +#include "base/numerics/basic_ops_impl.h" + +namespace base::numerics { + +// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. +// TODO(pkasting): Once C++23 is available, replace with std::byteswap. +template + requires(std::is_unsigned_v && std::is_integral_v) +inline constexpr T ByteSwap(T value) { + return numerics::internal::SwapBytes(value); +} + +// Returns a uint8_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromNativeEndian( + std::span bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint16_t U16FromNativeEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a uint32_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint32_t U32FromNativeEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a uint64_t with the value in `bytes` interpreted as the native endian +// encoding of the integer for the machine. +// +// This is suitable for decoding integers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr uint64_t U64FromNativeEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a float with the value in `bytes` interpreted as the native endian +// encoding of the number for the machine. +// +// This is suitable for decoding numbers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr float FloatFromNativeEndian( + std::span bytes) { + return std::bit_cast(U32FromNativeEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as the native endian +// encoding of the number for the machine. +// +// This is suitable for decoding numbers that were always kept in native +// encoding, such as when stored in shared-memory (or through IPC) as a byte +// buffer. Prefer an explicit little endian when storing and reading data from +// storage, and explicit big endian for network order. +inline constexpr double DoubleFromNativeEndian( + std::span bytes) { + return std::bit_cast(U64FromNativeEndian(bytes)); +} + +// Returns a uint8_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromLittleEndian( + std::span bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint16_t U16FromLittleEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a uint32_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint32_t U32FromLittleEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a uint64_t with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr uint64_t U64FromLittleEndian( + std::span bytes) { + return internal::FromLittleEndian(bytes); +} +// Returns a float with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr float FloatFromLittleEndian( + std::span bytes) { + return std::bit_cast(U32FromLittleEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as a little-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in little endian, +// which is a good practice with storing and reading data from storage. Use +// the native-endian versions when working with values that were always in +// memory, such as when stored in shared-memory (or through IPC) as a byte +// buffer. +inline constexpr double DoubleFromLittleEndian( + std::span bytes) { + return std::bit_cast(U64FromLittleEndian(bytes)); +} + +// Returns a uint8_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +// +// Note that since a single byte can have only one ordering, this just copies +// the byte out of the span. This provides a consistent function for the +// operation nonetheless. +inline constexpr uint8_t U8FromBigEndian(std::span bytes) { + return bytes[0]; +} +// Returns a uint16_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint16_t U16FromBigEndian(std::span bytes) { + return ByteSwap(internal::FromLittleEndian(bytes)); +} +// Returns a uint32_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint32_t U32FromBigEndian(std::span bytes) { + return ByteSwap(internal::FromLittleEndian(bytes)); +} +// Returns a uint64_t with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding integers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr uint64_t U64FromBigEndian(std::span bytes) { + return ByteSwap(internal::FromLittleEndian(bytes)); +} +// Returns a float with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr float FloatFromBigEndian(std::span bytes) { + return std::bit_cast(U32FromBigEndian(bytes)); +} +// Returns a double with the value in `bytes` interpreted as a big-endian +// encoding of the integer. +// +// This is suitable for decoding numbers encoded explicitly in big endian, such +// as for network order. Use the native-endian versions when working with values +// that were always in memory, such as when stored in shared-memory (or through +// IPC) as a byte buffer. +inline constexpr double DoubleFromBigEndian( + std::span bytes) { + return std::bit_cast(U64FromBigEndian(bytes)); +} + +// Returns a byte array holding the value of a uint8_t encoded as the native +// endian encoding of the integer for the machine. +// +// This is suitable for encoding integers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array U8ToNativeEndian(uint8_t val) { + return {val}; +} +// Returns a byte array holding the value of a uint16_t encoded as the native +// endian encoding of the integer for the machine. +// +// This is suitable for encoding integers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array U16ToNativeEndian(uint16_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a uint32_t encoded as the native +// endian encoding of the integer for the machine. +// +// This is suitable for encoding integers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array U32ToNativeEndian(uint32_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a uint64_t encoded as the native +// endian encoding of the integer for the machine. +// +// This is suitable for encoding integers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array U64ToNativeEndian(uint64_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a float encoded as the native +// endian encoding of the number for the machine. +// +// This is suitable for encoding numbers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array FloatToNativeEndian(float val) { + return U32ToNativeEndian(std::bit_cast(val)); +} +// Returns a byte array holding the value of a double encoded as the native +// endian encoding of the number for the machine. +// +// This is suitable for encoding numbers that will always be kept in native +// encoding, such as for storing in shared-memory (or sending through IPC) as a +// byte buffer. Prefer an explicit little endian when storing data into external +// storage, and explicit big endian for network order. +inline constexpr std::array DoubleToNativeEndian(double val) { + return U64ToNativeEndian(std::bit_cast(val)); +} + +// Returns a byte array holding the value of a uint8_t encoded as the +// little-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array U8ToLittleEndian(uint8_t val) { + return {val}; +} +// Returns a byte array holding the value of a uint16_t encoded as the +// little-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array U16ToLittleEndian(uint16_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a uint32_t encoded as the +// little-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array U32ToLittleEndian(uint32_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a uint64_t encoded as the +// little-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array U64ToLittleEndian(uint64_t val) { + return internal::ToLittleEndian(val); +} +// Returns a byte array holding the value of a float encoded as the +// little-endian encoding of the number. +// +// This is suitable for encoding numbers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array FloatToLittleEndian(float val) { + return internal::ToLittleEndian(std::bit_cast(val)); +} +// Returns a byte array holding the value of a double encoded as the +// little-endian encoding of the number. +// +// This is suitable for encoding numbers explicitly in little endian, which is +// a good practice with storing and reading data from storage. Use the +// native-endian versions when working with values that will always be in +// memory, such as when stored in shared-memory (or passed through IPC) as a +// byte buffer. +inline constexpr std::array DoubleToLittleEndian(double val) { + return internal::ToLittleEndian(std::bit_cast(val)); +} + +// Returns a byte array holding the value of a uint8_t encoded as the big-endian +// encoding of the integer. +// +// This is suitable for encoding integers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array U8ToBigEndian(uint8_t val) { + return {val}; +} +// Returns a byte array holding the value of a uint16_t encoded as the +// big-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array U16ToBigEndian(uint16_t val) { + return internal::ToLittleEndian(ByteSwap(val)); +} +// Returns a byte array holding the value of a uint32_t encoded as the +// big-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array U32ToBigEndian(uint32_t val) { + return internal::ToLittleEndian(ByteSwap(val)); +} +// Returns a byte array holding the value of a uint64_t encoded as the +// big-endian encoding of the integer. +// +// This is suitable for encoding integers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array U64ToBigEndian(uint64_t val) { + return internal::ToLittleEndian(ByteSwap(val)); +} +// Returns a byte array holding the value of a float encoded as the big-endian +// encoding of the number. +// +// This is suitable for encoding numbers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array FloatToBigEndian(float val) { + return internal::ToLittleEndian(ByteSwap(std::bit_cast(val))); +} +// Returns a byte array holding the value of a double encoded as the big-endian +// encoding of the number. +// +// This is suitable for encoding numbers explicitly in big endian, such as for +// network order. Use the native-endian versions when working with values that +// are always in memory, such as when stored in shared-memory (or passed through +// IPC) as a byte buffer. Use the little-endian encoding for storing and reading +// from storage. +inline constexpr std::array DoubleToBigEndian(double val) { + return internal::ToLittleEndian(ByteSwap(std::bit_cast(val))); +} + +} // namespace base::numerics + +#endif // BASE_NUMERICS_BYTE_CONVERSIONS_H_ diff --git a/naiveproxy/src/base/observer_list.h b/naiveproxy/src/base/observer_list.h index f4aad8cde0..b775118b0e 100644 --- a/naiveproxy/src/base/observer_list.h +++ b/naiveproxy/src/base/observer_list.h @@ -283,7 +283,7 @@ class ObserverList { // TODO(crbug.com/1423093): Turn this into a CHECK once very prevalent // failures are weeded out. if (HasObserver(obs)) { - NOTREACHED() << "Observers can only be added once!"; + DUMP_WILL_BE_NOTREACHED_NORETURN() << "Observers can only be added once!"; return; } observers_count_++; diff --git a/naiveproxy/src/base/pickle.cc b/naiveproxy/src/base/pickle.cc index 2189243c42..711775e144 100644 --- a/naiveproxy/src/base/pickle.cc +++ b/naiveproxy/src/base/pickle.cc @@ -322,16 +322,20 @@ void Pickle::WriteString16(const StringPiece16& value) { } void Pickle::WriteData(const char* data, size_t length) { - WriteData(std::string_view(data, length)); + WriteData(as_bytes(span(data, length))); } void Pickle::WriteData(std::string_view data) { + WriteData(as_byte_span(data)); +} + +void Pickle::WriteData(base::span data) { WriteInt(checked_cast(data.size())); - WriteBytes(as_byte_span(data)); + WriteBytes(data); } void Pickle::WriteBytes(const void* data, size_t length) { - WriteBytesCommon(make_span(reinterpret_cast(data), length)); + WriteBytesCommon(make_span(static_cast(data), length)); } void Pickle::WriteBytes(span data) { @@ -423,7 +427,7 @@ bool Pickle::PeekNext(size_t header_size, template void Pickle::WriteBytesStatic(const void* data) { - WriteBytesCommon(make_span(reinterpret_cast(data), length)); + WriteBytesCommon(make_span(static_cast(data), length)); } template void Pickle::WriteBytesStatic<2>(const void* data); diff --git a/naiveproxy/src/base/pickle.h b/naiveproxy/src/base/pickle.h index 4d98168e8f..79807b3619 100644 --- a/naiveproxy/src/base/pickle.h +++ b/naiveproxy/src/base/pickle.h @@ -220,8 +220,9 @@ class BASE_EXPORT Pickle { void WriteString16(const StringPiece16& value); // "Data" is a blob with a length. When you read it out you will be given the // length. See also WriteBytes. - // TODO(crbug.com/1490484): Migrate callers to the string_view version. + // TODO(crbug.com/1490484): Migrate callers to the span versions. void WriteData(const char* data, size_t length); + void WriteData(span data); void WriteData(std::string_view data); // "Bytes" is a blob with no length. The caller must specify the length both // when reading and writing. It is normally used to serialize PoD types of a @@ -272,6 +273,15 @@ class BASE_EXPORT Pickle { return header_ ? header_->payload_size : 0; } + base::span payload_bytes() const { + return base::as_bytes(base::make_span(payload(), payload_size())); + } + + protected: + // Returns size of the header, which can have default value, set by user or + // calculated by passed raw data. + size_t header_size() const { return header_size_; } + const char* payload() const { return reinterpret_cast(header_) + header_size_; } @@ -283,11 +293,6 @@ class BASE_EXPORT Pickle { return header_ ? payload() + payload_size() : NULL; } - protected: - // Returns size of the header, which can have default value, set by user or - // calculated by passed raw data. - size_t header_size() const { return header_size_; } - char* mutable_payload() { return reinterpret_cast(header_) + header_size_; } diff --git a/naiveproxy/src/base/power_monitor/power_monitor_device_source_android.cc b/naiveproxy/src/base/power_monitor/power_monitor_device_source_android.cc index 82eae92012..7a8fd3f50e 100644 --- a/naiveproxy/src/base/power_monitor/power_monitor_device_source_android.cc +++ b/naiveproxy/src/base/power_monitor/power_monitor_device_source_android.cc @@ -81,18 +81,18 @@ void JNI_PowerMonitor_OnThermalStatusChanged(JNIEnv* env, int thermal_status) { } // namespace android bool PowerMonitorDeviceSource::IsOnBatteryPower() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return base::android::Java_PowerMonitor_isBatteryPower(env); } int PowerMonitorDeviceSource::GetRemainingBatteryCapacity() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return base::android::Java_PowerMonitor_getRemainingBatteryCapacity(env); } PowerThermalObserver::DeviceThermalState PowerMonitorDeviceSource::GetCurrentThermalState() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return android::MapToDeviceThermalState( android::Java_PowerMonitor_getCurrentThermalStatus(env)); } diff --git a/naiveproxy/src/base/process/port_provider_mac.cc b/naiveproxy/src/base/process/port_provider_mac.cc index 2ebb22c0de..e7703c0f97 100644 --- a/naiveproxy/src/base/process/port_provider_mac.cc +++ b/naiveproxy/src/base/process/port_provider_mac.cc @@ -20,12 +20,14 @@ void PortProvider::RemoveObserver(Observer* observer) { observer_list_->RemoveObserver(observer); } -void PortProvider::NotifyObservers(ProcessHandle process) { - observer_list_->Notify(FROM_HERE, &Observer::OnReceivedTaskPort, process); +void PortProvider::NotifyObservers(ProcessHandle process_handle) { + observer_list_->Notify(FROM_HERE, &Observer::OnReceivedTaskPort, + process_handle); } -mach_port_t SelfPortProvider::TaskForPid(base::ProcessHandle process) const { - DCHECK(base::Process(process).is_current()); +mach_port_t SelfPortProvider::TaskForHandle( + base::ProcessHandle process_handle) const { + DCHECK(base::Process(process_handle).is_current()); return mach_task_self(); } diff --git a/naiveproxy/src/base/process/port_provider_mac.h b/naiveproxy/src/base/process/port_provider_mac.h index 74cab3339a..c3f54812f7 100644 --- a/naiveproxy/src/base/process/port_provider_mac.h +++ b/naiveproxy/src/base/process/port_provider_mac.h @@ -33,12 +33,12 @@ class BASE_EXPORT PortProvider { // received for a given process. // This notification is guaranteed to be sent on the same task runner where // the observer was added. - virtual void OnReceivedTaskPort(ProcessHandle process) = 0; + virtual void OnReceivedTaskPort(ProcessHandle process_handle) = 0; }; - // Returns the mach task port for |process| if possible, or else - // |MACH_PORT_NULL|. - virtual mach_port_t TaskForPid(ProcessHandle process) const = 0; + // Returns the mach task port for `process_handle` if possible, or else + // `MACH_PORT_NULL`. + virtual mach_port_t TaskForHandle(ProcessHandle process_handle) const = 0; // Observer interface. void AddObserver(Observer* observer); @@ -46,7 +46,7 @@ class BASE_EXPORT PortProvider { protected: // Called by subclasses to send a notification to observers. - void NotifyObservers(ProcessHandle process); + void NotifyObservers(ProcessHandle process_handle); private: scoped_refptr> observer_list_; @@ -55,7 +55,7 @@ class BASE_EXPORT PortProvider { // Port provider that returns the calling process's task port, ignoring its // argument. class BASE_EXPORT SelfPortProvider : public base::PortProvider { - mach_port_t TaskForPid(base::ProcessHandle process) const override; + mach_port_t TaskForHandle(base::ProcessHandle process_handle) const override; }; } // namespace base diff --git a/naiveproxy/src/base/process/process_android.cc b/naiveproxy/src/base/process/process_android.cc index e90451eaca..54ffd4d2cd 100644 --- a/naiveproxy/src/base/process/process_android.cc +++ b/naiveproxy/src/base/process/process_android.cc @@ -4,7 +4,7 @@ #include "base/process/process.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/process/internal_linux.h" namespace base { diff --git a/naiveproxy/src/base/process/process_mac.cc b/naiveproxy/src/base/process/process_mac.cc index 9331a05e9f..f7b0e75081 100644 --- a/naiveproxy/src/base/process/process_mac.cc +++ b/naiveproxy/src/base/process/process_mac.cc @@ -164,7 +164,7 @@ Process::Priority Process::GetPriority(PortProvider* port_provider) const { CHECK(IsValid()); CHECK(port_provider); - mach_port_t task_port = port_provider->TaskForPid(Pid()); + mach_port_t task_port = port_provider->TaskForHandle(Handle()); if (task_port == TASK_NULL) { // Upon failure, return the default value. return Priority::kUserBlocking; @@ -201,7 +201,7 @@ bool Process::SetPriority(PortProvider* port_provider, Priority priority) { return false; } - mach_port_t task_port = port_provider->TaskForPid(Pid()); + mach_port_t task_port = port_provider->TaskForHandle(Handle()); if (task_port == TASK_NULL) { return false; } diff --git a/naiveproxy/src/base/process/process_metrics.cc b/naiveproxy/src/base/process/process_metrics.cc index a3b441d798..8405de7d86 100644 --- a/naiveproxy/src/base/process/process_metrics.cc +++ b/naiveproxy/src/base/process/process_metrics.cc @@ -7,7 +7,7 @@ #include #include "base/check.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/numerics/safe_conversions.h" #include "base/values.h" #include "build/build_config.h" diff --git a/naiveproxy/src/base/process/process_metrics.h b/naiveproxy/src/base/process/process_metrics.h index 3c876329af..5f8cac1402 100644 --- a/naiveproxy/src/base/process/process_metrics.h +++ b/naiveproxy/src/base/process/process_metrics.h @@ -250,7 +250,7 @@ class BASE_EXPORT ProcessMetrics { uint64_t absolute_package_idle_wakeups); // Queries the port provider if it's set. - mach_port_t TaskForPid(ProcessHandle process) const; + mach_port_t TaskForHandle(ProcessHandle process_handle) const; #endif #if BUILDFLAG(IS_WIN) @@ -421,6 +421,12 @@ BASE_EXPORT extern const char kProcSelfExe[]; BASE_EXPORT bool ParseProcMeminfo(StringPiece input, SystemMemoryInfoKB* meminfo); +// Returns the memory committed by the system in KBytes, as from +// GetSystemCommitCharge(), using data from `meminfo` instead of /proc/meminfo. +// Exposed for testing. +BASE_EXPORT size_t +GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo); + // Data from /proc/vmstat. struct BASE_EXPORT VmStatInfo { // Serializes the platform specific fields to value. diff --git a/naiveproxy/src/base/process/process_metrics_apple.cc b/naiveproxy/src/base/process/process_metrics_apple.cc index 54dd5f2faf..1a23c8a083 100644 --- a/naiveproxy/src/base/process/process_metrics_apple.cc +++ b/naiveproxy/src/base/process/process_metrics_apple.cc @@ -16,6 +16,7 @@ #include "base/logging.h" #include "base/mac/mac_util.h" #include "base/memory/ptr_util.h" +#include "base/notimplemented.h" #include "base/numerics/safe_math.h" #include "base/time/time.h" #include "build/build_config.h" @@ -79,21 +80,21 @@ bool GetPowerInfo(mach_port_t task, task_power_info* power_info_data) { } // namespace // Implementations of ProcessMetrics class shared by Mac and iOS. -mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const { +mach_port_t ProcessMetrics::TaskForHandle(ProcessHandle process_handle) const { mach_port_t task = MACH_PORT_NULL; #if BUILDFLAG(IS_MAC) if (port_provider_) { - task = port_provider_->TaskForPid(process_); + task = port_provider_->TaskForHandle(process_); } #endif - if (task == MACH_PORT_NULL && process_ == getpid()) { + if (task == MACH_PORT_NULL && process_handle == getpid()) { task = mach_task_self(); } return task; } TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { - mach_port_t task = TaskForPid(process_); + mach_port_t task = TaskForHandle(process_); if (task == MACH_PORT_NULL) { return TimeDelta(); } @@ -143,7 +144,7 @@ TimeDelta ProcessMetrics::GetCumulativeCPUUsage() { } int ProcessMetrics::GetPackageIdleWakeupsPerSecond() { - mach_port_t task = TaskForPid(process_); + mach_port_t task = TaskForHandle(process_); task_power_info power_info_data; GetPowerInfo(task, &power_info_data); @@ -163,7 +164,7 @@ int ProcessMetrics::GetPackageIdleWakeupsPerSecond() { } int ProcessMetrics::GetIdleWakeupsPerSecond() { - mach_port_t task = TaskForPid(process_); + mach_port_t task = TaskForHandle(process_); task_power_info power_info_data; GetPowerInfo(task, &power_info_data); diff --git a/naiveproxy/src/base/process/process_metrics_linux.cc b/naiveproxy/src/base/process/process_metrics_linux.cc index 97eb24d28f..8fd27a59a1 100644 --- a/naiveproxy/src/base/process/process_metrics_linux.cc +++ b/naiveproxy/src/base/process/process_metrics_linux.cc @@ -22,6 +22,7 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/notreached.h" +#include "base/numerics/clamped_math.h" #include "base/numerics/safe_conversions.h" #include "base/process/internal_linux.h" #include "base/process/process_metrics_iocounters.h" @@ -228,8 +229,16 @@ size_t GetSystemCommitCharge() { SystemMemoryInfoKB meminfo; if (!GetSystemMemoryInfo(&meminfo)) return 0; - return checked_cast(meminfo.total - meminfo.free - meminfo.buffers - - meminfo.cached); + return GetSystemCommitChargeFromMeminfo(meminfo); +} + +size_t GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo) { + // TODO(crbug.com/315988925): This math is incorrect: `cached` can be very + // large so that `free` + `buffers` + `cached` > `total`. Replace this with a + // more meaningful metric or remove it. In the meantime, convert underflows to + // 0 instead of crashing. + return ClampedNumeric(meminfo.total) - meminfo.free - + meminfo.buffers - meminfo.cached; } int ParseProcStatCPU(StringPiece input) { diff --git a/naiveproxy/src/base/process/process_metrics_win.cc b/naiveproxy/src/base/process/process_metrics_win.cc index 35fe6f67d2..ff22d52bd9 100644 --- a/naiveproxy/src/base/process/process_metrics_win.cc +++ b/naiveproxy/src/base/process/process_metrics_win.cc @@ -180,7 +180,7 @@ TimeDelta ProcessMetrics::GetPreciseCumulativeCPUUsage() { ULONG64 process_cycle_time = 0; if (!QueryProcessCycleTime(process_.get(), &process_cycle_time)) { - NOTREACHED(); + DUMP_WILL_BE_NOTREACHED_NORETURN(); return TimeDelta(); } diff --git a/naiveproxy/src/base/process/process_posix.cc b/naiveproxy/src/base/process/process_posix.cc index 1f18dd2cec..1806e34915 100644 --- a/naiveproxy/src/base/process/process_posix.cc +++ b/naiveproxy/src/base/process/process_posix.cc @@ -15,7 +15,7 @@ #include "base/clang_profiling_buildflags.h" #include "base/files/scoped_file.h" #include "base/logging.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/posix/eintr_wrapper.h" #include "base/process/kill.h" #include "base/threading/thread_restrictions.h" diff --git a/naiveproxy/src/base/profiler/stack_copier_signal.cc b/naiveproxy/src/base/profiler/stack_copier_signal.cc index 5c749dc3bb..36bc79e11c 100644 --- a/naiveproxy/src/base/profiler/stack_copier_signal.cc +++ b/naiveproxy/src/base/profiler/stack_copier_signal.cc @@ -15,6 +15,7 @@ #include #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ptr_exclusion.h" #include "base/notreached.h" #include "base/profiler/register_context.h" #include "base/profiler/stack_buffer.h" @@ -99,33 +100,39 @@ class ScopedEventSignaller { ~ScopedEventSignaller() { event_->Signal(); } private: - raw_ptr event_; + // RAW_PTR_EXCLUSION: raw_ptr<> is not safe within a signal handler. + RAW_PTR_EXCLUSION AsyncSafeWaitableEvent* event_; }; // Struct to store the arguments to the signal handler. struct HandlerParams { uintptr_t stack_base_address; + // RAW_PTR_EXCLUSION: raw_ptr<> is not safe within a signal handler, + // as the target thread could be in the middle of an allocation and + // PartitionAlloc's external invariants might be violated. So all + // the pointers below are C pointers. + // The event is signalled when signal handler is done executing. - raw_ptr event; + RAW_PTR_EXCLUSION AsyncSafeWaitableEvent* event; // Return values: // Successfully copied the stack segment. - raw_ptr success; + RAW_PTR_EXCLUSION bool* success; // The thread context of the leaf function. - raw_ptr context; + RAW_PTR_EXCLUSION mcontext_t* context; // Buffer to copy the stack segment. - raw_ptr stack_buffer; - raw_ptr stack_copy_bottom; + RAW_PTR_EXCLUSION StackBuffer* stack_buffer; + RAW_PTR_EXCLUSION const uint8_t** stack_copy_bottom; // The timestamp when the stack was copied. - raw_ptr> maybe_timestamp; + RAW_PTR_EXCLUSION absl::optional* maybe_timestamp; // The delegate provided to the StackCopier. - raw_ptr stack_copier_delegate; + RAW_PTR_EXCLUSION StackCopier::Delegate* stack_copier_delegate; }; // Pointer to the parameters to be "passed" to the CopyStackSignalHandler() from diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler_java_test_util.cc b/naiveproxy/src/base/profiler/stack_sampling_profiler_java_test_util.cc index 77bb9a2e0d..45dda4c3e2 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler_java_test_util.cc +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler_java_test_util.cc @@ -34,7 +34,7 @@ void JNI_TestSupport_InvokeCallbackFunction(JNIEnv* env, jlong context) { } FunctionAddressRange callWithJavaFunction(OnceClosure closure) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); UnwinderJavaTestSupportParams params{std::move(closure), {}}; base::Java_TestSupport_callWithJavaFunction( env, reinterpret_cast(¶ms)); diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.cc b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.cc index eaedcc0a30..fc41fa88e6 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.cc +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.cc @@ -364,7 +364,7 @@ void ExpectStackContains(const std::vector& stack, for (; frame_it != stack.end() && function_it != functions.end(); ++frame_it) { if (frame_it->instruction_pointer >= - reinterpret_cast(function_it->start) && + reinterpret_cast(function_it->start.get()) && frame_it->instruction_pointer <= reinterpret_cast(function_it->end.get())) { ++function_it; @@ -410,7 +410,7 @@ void ExpectStackDoesNotContain( for (const auto& frame : stack) { for (const auto& function : functions) { if (frame.instruction_pointer >= - reinterpret_cast(function.start) && + reinterpret_cast(function.start.get()) && frame.instruction_pointer <= reinterpret_cast(function.end.get())) { seen_functions.insert(function); diff --git a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h index 8bf6db4605..17f4f6ec3b 100644 --- a/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h +++ b/naiveproxy/src/base/profiler/stack_sampling_profiler_test_util.h @@ -12,7 +12,6 @@ #include "base/base_export.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" -#include "base/memory/raw_ptr_exclusion.h" #include "base/native_library.h" #include "base/profiler/frame.h" #include "base/profiler/sampling_profiler_thread_token.h" @@ -52,9 +51,7 @@ class TargetThread : public PlatformThread::Delegate { // Addresses near the start and end of a function. struct FunctionAddressRange { - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #in-out-param-ref - RAW_PTR_EXCLUSION const void* start; + raw_ptr start; raw_ptr end; }; diff --git a/naiveproxy/src/base/rand_util.cc b/naiveproxy/src/base/rand_util.cc index 0be3aaa565..f164640db9 100644 --- a/naiveproxy/src/base/rand_util.cc +++ b/naiveproxy/src/base/rand_util.cc @@ -9,17 +9,22 @@ #include #include +#include #include #include "base/check_op.h" -#include "base/strings/string_util.h" #include "base/time/time.h" namespace base { namespace { -bool g_subsampling_enabled = true; +// A MetricSubsampler instance is not thread-safe. However, the global +// sampling state may be read concurrently with writing it via testing +// scopers, hence the need to use atomics. All operations use +// memory_order_relaxed because there are no dependent memory accesses. +std::atomic g_subsampling_always_sample = false; +std::atomic g_subsampling_never_sample = false; } // namespace @@ -107,8 +112,8 @@ uint64_t RandGenerator(uint64_t range) { std::string RandBytesAsString(size_t length) { DCHECK_GT(length, 0u); - std::string result; - RandBytes(WriteInto(&result, length + 1), length); + std::string result(length, '\0'); + RandBytes(result.data(), length); return result; } @@ -163,17 +168,40 @@ double InsecureRandomGenerator::RandDouble() { MetricsSubSampler::MetricsSubSampler() = default; bool MetricsSubSampler::ShouldSample(double probability) { - return !g_subsampling_enabled || generator_.RandDouble() < probability; + if (g_subsampling_always_sample.load(std::memory_order_relaxed)) { + return true; + } + if (g_subsampling_never_sample.load(std::memory_order_relaxed)) { + return false; + } + + return generator_.RandDouble() < probability; } -MetricsSubSampler::ScopedDisableForTesting::ScopedDisableForTesting() { - DCHECK(g_subsampling_enabled); - g_subsampling_enabled = false; +MetricsSubSampler::ScopedAlwaysSampleForTesting:: + ScopedAlwaysSampleForTesting() { + DCHECK(!g_subsampling_always_sample.load(std::memory_order_relaxed)); + DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed)); + g_subsampling_always_sample.store(true, std::memory_order_relaxed); } -MetricsSubSampler::ScopedDisableForTesting::~ScopedDisableForTesting() { - DCHECK(!g_subsampling_enabled); - g_subsampling_enabled = true; +MetricsSubSampler::ScopedAlwaysSampleForTesting:: + ~ScopedAlwaysSampleForTesting() { + DCHECK(g_subsampling_always_sample.load(std::memory_order_relaxed)); + DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed)); + g_subsampling_always_sample.store(false, std::memory_order_relaxed); +} + +MetricsSubSampler::ScopedNeverSampleForTesting::ScopedNeverSampleForTesting() { + DCHECK(!g_subsampling_always_sample.load(std::memory_order_relaxed)); + DCHECK(!g_subsampling_never_sample.load(std::memory_order_relaxed)); + g_subsampling_never_sample.store(true, std::memory_order_relaxed); +} + +MetricsSubSampler::ScopedNeverSampleForTesting::~ScopedNeverSampleForTesting() { + DCHECK(!g_subsampling_always_sample); + DCHECK(g_subsampling_never_sample); + g_subsampling_never_sample.store(false, std::memory_order_relaxed); } } // namespace base diff --git a/naiveproxy/src/base/rand_util.h b/naiveproxy/src/base/rand_util.h index 00e901a326..a24e931221 100644 --- a/naiveproxy/src/base/rand_util.h +++ b/naiveproxy/src/base/rand_util.h @@ -219,11 +219,22 @@ class BASE_EXPORT MetricsSubSampler { MetricsSubSampler(); bool ShouldSample(double probability); - // Disables subsampling in a scope. Useful for testing. - class BASE_EXPORT ScopedDisableForTesting { + // Make any call to ShouldSample for any instance of MetricsSubSampler + // return true for testing. Cannot be used in conjunction with + // ScopedNeverSampleForTesting. + class BASE_EXPORT ScopedAlwaysSampleForTesting { public: - ScopedDisableForTesting(); - ~ScopedDisableForTesting(); + ScopedAlwaysSampleForTesting(); + ~ScopedAlwaysSampleForTesting(); + }; + + // Make any call to ShouldSample for any instance of MetricsSubSampler + // return false for testing. Cannot be used in conjunction with + // ScopedAlwaysSampleForTesting. + class BASE_EXPORT ScopedNeverSampleForTesting { + public: + ScopedNeverSampleForTesting(); + ~ScopedNeverSampleForTesting(); }; private: diff --git a/naiveproxy/src/base/rand_util_fuchsia.cc b/naiveproxy/src/base/rand_util_fuchsia.cc index 78046349e1..ee9458989b 100644 --- a/naiveproxy/src/base/rand_util_fuchsia.cc +++ b/naiveproxy/src/base/rand_util_fuchsia.cc @@ -53,7 +53,7 @@ void RandBytes(span output) { } void RandBytes(void* output, size_t output_length) { - RandBytes(make_span(reinterpret_cast(output), output_length)); + RandBytes(make_span(static_cast(output), output_length)); } namespace internal { diff --git a/naiveproxy/src/base/rand_util_nacl.cc b/naiveproxy/src/base/rand_util_nacl.cc index dfa72634e9..b7f2395464 100644 --- a/naiveproxy/src/base/rand_util_nacl.cc +++ b/naiveproxy/src/base/rand_util_nacl.cc @@ -24,7 +24,7 @@ void RandBytes(span output) { } void RandBytes(void* output, size_t output_length) { - RandBytes(make_span(reinterpret_cast(output), output_length)); + RandBytes(make_span(static_cast(output), output_length)); } } // namespace base diff --git a/naiveproxy/src/base/rand_util_posix.cc b/naiveproxy/src/base/rand_util_posix.cc index d0da3d7cd3..d186c28e42 100644 --- a/naiveproxy/src/base/rand_util_posix.cc +++ b/naiveproxy/src/base/rand_util_posix.cc @@ -236,7 +236,7 @@ void RandBytes(span output) { } void RandBytes(void* output, size_t output_length) { - RandBytes(make_span(reinterpret_cast(output), output_length)); + RandBytes(make_span(static_cast(output), output_length)); } int GetUrandomFD() { diff --git a/naiveproxy/src/base/rand_util_win.cc b/naiveproxy/src/base/rand_util_win.cc index 6aae763d98..299e54300a 100644 --- a/naiveproxy/src/base/rand_util_win.cc +++ b/naiveproxy/src/base/rand_util_win.cc @@ -88,7 +88,7 @@ void RandBytes(span output) { } void RandBytes(void* output, size_t output_length) { - RandBytes(make_span(reinterpret_cast(output), output_length), + RandBytes(make_span(static_cast(output), output_length), /*avoid_allocation=*/false); } diff --git a/naiveproxy/src/base/run_loop.cc b/naiveproxy/src/base/run_loop.cc index ce2473e3fa..2af8260eea 100644 --- a/naiveproxy/src/base/run_loop.cc +++ b/naiveproxy/src/base/run_loop.cc @@ -201,7 +201,6 @@ RepeatingClosure RunLoop::QuitClosure() { // QuitClosure() from the owning thread before Run() or invoke Quit() directly // (which is thread-safe). DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - allow_quit_current_deprecated_ = false; return BindRepeating( &ProxyToTaskRunner, origin_task_runner_, @@ -213,7 +212,6 @@ RepeatingClosure RunLoop::QuitWhenIdleClosure() { // QuitWhenIdleClosure() from the owning thread before Run() or invoke // QuitWhenIdle() directly (which is thread-safe). DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - allow_quit_current_deprecated_ = false; return BindRepeating( &ProxyToTaskRunner, origin_task_runner_, @@ -246,31 +244,6 @@ void RunLoop::RemoveNestingObserverOnCurrentThread(NestingObserver* observer) { delegate->nesting_observers_.RemoveObserver(observer); } -// static -void RunLoop::QuitCurrentDeprecated() { - DCHECK(IsRunningOnCurrentThread()); - DCHECK(delegate->active_run_loops_.top()->allow_quit_current_deprecated_) - << "Please migrate off QuitCurrentDeprecated(), e.g. to QuitClosure()."; - delegate->active_run_loops_.top()->Quit(); -} - -// static -void RunLoop::QuitCurrentWhenIdleDeprecated() { - DCHECK(IsRunningOnCurrentThread()); - DCHECK(delegate->active_run_loops_.top()->allow_quit_current_deprecated_) - << "Please migrate off QuitCurrentWhenIdleDeprecated(), e.g. to " - "QuitWhenIdleClosure()."; - delegate->active_run_loops_.top()->QuitWhenIdle(); -} - -// static -RepeatingClosure RunLoop::QuitCurrentWhenIdleClosureDeprecated() { - // TODO(844016): Fix callsites and enable this check, or remove the API. - // DCHECK(delegate->active_run_loops_.top()->allow_quit_current_deprecated_) - // << "Please migrate off QuitCurrentWhenIdleClosureDeprecated(), e.g to " - // "QuitWhenIdleClosure()."; - return BindRepeating(&RunLoop::QuitCurrentWhenIdleDeprecated); -} #if DCHECK_IS_ON() ScopedDisallowRunningRunLoop::ScopedDisallowRunningRunLoop() diff --git a/naiveproxy/src/base/run_loop.h b/naiveproxy/src/base/run_loop.h index a20fd1e0e0..1e94e8e699 100644 --- a/naiveproxy/src/base/run_loop.h +++ b/naiveproxy/src/base/run_loop.h @@ -252,16 +252,6 @@ class BASE_EXPORT RunLoop { // on forever bound to that thread (including its destruction). static void RegisterDelegateForCurrentThread(Delegate* new_delegate); - // Quits the active RunLoop (when idle) -- there must be one. These were - // introduced as prefered temporary replacements to the long deprecated - // MessageLoop::Quit(WhenIdle)(Closure) methods. Callers should properly plumb - // a reference to the appropriate RunLoop instance (or its QuitClosure) - // instead of using these in order to link Run()/Quit() to a single RunLoop - // instance and increase readability. - static void QuitCurrentDeprecated(); - static void QuitCurrentWhenIdleDeprecated(); - [[nodiscard]] static RepeatingClosure QuitCurrentWhenIdleClosureDeprecated(); - // Support for //base/test/scoped_run_loop_timeout.h. // This must be public for access by the implementation code in run_loop.cc. struct BASE_EXPORT RunLoopTimeout { @@ -319,11 +309,6 @@ class BASE_EXPORT RunLoop { // stored here rather than pushed to Delegate to support nested RunLoops. bool quit_when_idle_ = false; - // True if use of QuitCurrent*Deprecated() is allowed. Taking a Quit*Closure() - // from a RunLoop implicitly sets this to false, so QuitCurrent*Deprecated() - // cannot be used while that RunLoop is being Run(). - bool allow_quit_current_deprecated_ = true; - // RunLoop is not thread-safe. Its state/methods, unless marked as such, may // not be accessed from any other sequence than the thread it was constructed // on. Exception: RunLoop can be safely accessed from one other sequence (or diff --git a/naiveproxy/src/base/sampling_heap_profiler/poisson_allocation_sampler.cc b/naiveproxy/src/base/sampling_heap_profiler/poisson_allocation_sampler.cc index 9c449e95ee..59c135f0a5 100644 --- a/naiveproxy/src/base/sampling_heap_profiler/poisson_allocation_sampler.cc +++ b/naiveproxy/src/base/sampling_heap_profiler/poisson_allocation_sampler.cc @@ -425,7 +425,7 @@ void PoissonAllocationSampler::RemoveSamplesObserver( ScopedMuteThreadSamples no_reentrancy_scope; AutoLock lock(mutex_); auto it = ranges::find(observers_, observer); - DCHECK(it != observers_.end()); + CHECK(it != observers_.end(), base::NotFatalUntil::M125); observers_.erase(it); // Stop the profiler if there are no more observers. Setting/resetting diff --git a/naiveproxy/src/base/scoped_multi_source_observation.h b/naiveproxy/src/base/scoped_multi_source_observation.h index 3eadc331d4..5614fea175 100644 --- a/naiveproxy/src/base/scoped_multi_source_observation.h +++ b/naiveproxy/src/base/scoped_multi_source_observation.h @@ -57,6 +57,7 @@ class ScopedMultiSourceObservation { // Adds the object passed to the constructor as an observer on |source|. void AddObservation(Source* source) { + CHECK(!IsObservingSource(source)); sources_.push_back(source); Traits::AddObserver(source, observer_); } diff --git a/naiveproxy/src/base/sequence_token.cc b/naiveproxy/src/base/sequence_token.cc index 503f9f049e..4f4dc63a24 100644 --- a/naiveproxy/src/base/sequence_token.cc +++ b/naiveproxy/src/base/sequence_token.cc @@ -7,7 +7,8 @@ #include "base/atomic_sequence_num.h" #include "third_party/abseil-cpp/absl/base/attributes.h" -namespace base::internal { +namespace base { +namespace internal { namespace { @@ -18,6 +19,7 @@ base::AtomicSequenceNumber g_task_token_generator; ABSL_CONST_INIT thread_local SequenceToken current_sequence_token; ABSL_CONST_INIT thread_local TaskToken current_task_token; ABSL_CONST_INIT thread_local bool current_task_is_thread_bound = true; +ABSL_CONST_INIT thread_local bool current_task_is_running_synchronously = false; } // namespace @@ -73,19 +75,32 @@ bool CurrentTaskIsThreadBound() { return current_task_is_thread_bound; } -TaskScope::TaskScope(SequenceToken sequence_token, bool is_single_threaded) +TaskScope::TaskScope(SequenceToken sequence_token, + bool is_single_threaded, + bool is_running_synchronously) : previous_task_token_(TaskToken::GetForCurrentThread()), previous_sequence_token_(SequenceToken::GetForCurrentThread()), - previous_task_is_thread_bound_(current_task_is_thread_bound) { + previous_task_is_thread_bound_(current_task_is_thread_bound), + previous_task_is_running_synchronously_( + current_task_is_running_synchronously) { current_task_token = TaskToken::Create(); current_sequence_token = sequence_token; current_task_is_thread_bound = is_single_threaded; + current_task_is_running_synchronously = is_running_synchronously; } TaskScope::~TaskScope() { current_task_token = previous_task_token_; current_sequence_token = previous_sequence_token_; current_task_is_thread_bound = previous_task_is_thread_bound_; + current_task_is_running_synchronously = + previous_task_is_running_synchronously_; } -} // namespace base::internal +} // namespace internal + +bool CurrentTaskIsRunningSynchronously() { + return internal::current_task_is_running_synchronously; +} + +} // namespace base diff --git a/naiveproxy/src/base/sequence_token.h b/naiveproxy/src/base/sequence_token.h index f684bb3b92..060a235eac 100644 --- a/naiveproxy/src/base/sequence_token.h +++ b/naiveproxy/src/base/sequence_token.h @@ -9,7 +9,8 @@ #include "base/auto_reset.h" #include "base/base_export.h" -namespace base::internal { +namespace base { +namespace internal { // A token that identifies a series of sequenced work items (i.e. tasks, native // message handlers, code blocks running outside or a `RunLoop`, etc. that are @@ -104,7 +105,11 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] TaskScope { // that this task is part of (may be unique if this task isn't mutually // exclusive with any other work item). `is_thread_bound` sets the value // returned by `CurrentTaskIsThreadBound()` within the scope. - explicit TaskScope(SequenceToken sequence_token, bool is_thread_bound); + // `is_running_synchronously` is true iff this is instantiated for a task run + // synchronously by `RunOrPostTask()`. + explicit TaskScope(SequenceToken sequence_token, + bool is_thread_bound, + bool is_running_synchronously = false); TaskScope(const TaskScope&) = delete; TaskScope& operator=(const TaskScope&) = delete; ~TaskScope(); @@ -113,8 +118,14 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] TaskScope { const TaskToken previous_task_token_; const SequenceToken previous_sequence_token_; const bool previous_task_is_thread_bound_; + const bool previous_task_is_running_synchronously_; }; -} // namespace base::internal +} // namespace internal + +// Returns true if the current task is run synchronously by `RunOrPostTask()`. +bool BASE_EXPORT CurrentTaskIsRunningSynchronously(); + +} // namespace base #endif // BASE_SEQUENCE_TOKEN_H_ diff --git a/naiveproxy/src/base/strings/string_number_conversions.cc b/naiveproxy/src/base/strings/string_number_conversions.cc index 735feda233..2db17f24ad 100644 --- a/naiveproxy/src/base/strings/string_number_conversions.cc +++ b/naiveproxy/src/base/strings/string_number_conversions.cc @@ -120,7 +120,7 @@ bool StringToDouble(StringPiece16 input, double* output) { } std::string HexEncode(const void* bytes, size_t size) { - return HexEncode(span(reinterpret_cast(bytes), size)); + return HexEncode(span(static_cast(bytes), size)); } std::string HexEncode(span bytes) { @@ -134,6 +134,10 @@ std::string HexEncode(span bytes) { return ret; } +std::string HexEncode(StringPiece chars) { + return HexEncode(base::as_byte_span(chars)); +} + bool HexStringToInt(StringPiece input, int* output) { return internal::HexStringToIntImpl(input, *output); } diff --git a/naiveproxy/src/base/strings/string_number_conversions.h b/naiveproxy/src/base/strings/string_number_conversions.h index 281d250d25..55c28d6642 100644 --- a/naiveproxy/src/base/strings/string_number_conversions.h +++ b/naiveproxy/src/base/strings/string_number_conversions.h @@ -106,6 +106,7 @@ BASE_EXPORT bool StringToDouble(StringPiece16 input, double* output); // std::numeric_limits::max() / 2 BASE_EXPORT std::string HexEncode(const void* bytes, size_t size); BASE_EXPORT std::string HexEncode(base::span bytes); +BASE_EXPORT std::string HexEncode(StringPiece chars); // Appends a hex representation of `byte`, as two uppercase (by default) // characters, to `output`. This is a useful primitive in larger conversion diff --git a/naiveproxy/src/base/strings/string_tokenizer.h b/naiveproxy/src/base/strings/string_tokenizer.h index e4a24bd25d..5d4e8bc512 100644 --- a/naiveproxy/src/base/strings/string_tokenizer.h +++ b/naiveproxy/src/base/strings/string_tokenizer.h @@ -103,10 +103,17 @@ namespace base { // test // // +// TODO(danakj): This class is templated on the container and the iterator type, +// but it strictly only needs to care about the `CharType`. However many users +// expect to work with string and string::iterator for historical reasons. When +// they are all working with `string_view`, then this class can be made to +// unconditoinally use `std::basic_string_view` and vend iterators of +// that type, and we can drop the `str` and `const_iterator` aliases. template class StringTokenizerT { public: - typedef typename str::value_type char_type; + using char_type = typename str::value_type; + using owning_str = std::basic_string; // Options that may be pass to set_options() enum { @@ -139,7 +146,7 @@ class StringTokenizerT { // the constructor), but caution must still be exercised. StringTokenizerT( const str& string, - const str& delims, + const owning_str& delims, WhitespacePolicy whitespace_policy = WhitespacePolicy::kIncludeInTokens) { Init(string.begin(), string.end(), delims, whitespace_policy); } @@ -151,7 +158,7 @@ class StringTokenizerT { StringTokenizerT( const_iterator string_begin, const_iterator string_end, - const str& delims, + const owning_str& delims, WhitespacePolicy whitespace_policy = WhitespacePolicy::kIncludeInTokens) { Init(string_begin, string_end, delims, whitespace_policy); } @@ -164,7 +171,7 @@ class StringTokenizerT { // it ignores delimiters that it finds. It switches out of this mode once it // finds another instance of the quote char. If a backslash is encountered // within a quoted string, then the next character is skipped. - void set_quote_chars(const str& quotes) { quotes_ = quotes; } + void set_quote_chars(const owning_str& quotes) { quotes_ = quotes; } // Call this method to advance the tokenizer to the next delimiter. This // returns false if the tokenizer is complete. This method must be called @@ -199,7 +206,7 @@ class StringTokenizerT { private: void Init(const_iterator string_begin, const_iterator string_end, - const str& delims, + const owning_str& delims, WhitespacePolicy whitespace_policy) { start_pos_ = string_begin; token_begin_ = string_begin; @@ -309,9 +316,13 @@ class StringTokenizerT { return false; } - bool IsDelim(char_type c) const { return delims_.find(c) != str::npos; } + bool IsDelim(char_type c) const { + return delims_.find(c) != owning_str::npos; + } - bool IsQuote(char_type c) const { return quotes_.find(c) != str::npos; } + bool IsQuote(char_type c) const { + return quotes_.find(c) != owning_str::npos; + } struct AdvanceState { bool in_quote; @@ -343,8 +354,8 @@ class StringTokenizerT { const_iterator token_begin_; const_iterator token_end_; const_iterator end_; - str delims_; - str quotes_; + owning_str delims_; + owning_str quotes_; int options_; bool token_is_delim_; WhitespacePolicy whitespace_policy_; @@ -352,6 +363,8 @@ class StringTokenizerT { typedef StringTokenizerT StringTokenizer; +typedef StringTokenizerT + StringViewTokenizer; typedef StringTokenizerT String16Tokenizer; typedef StringTokenizerT CStringTokenizer; diff --git a/naiveproxy/src/base/strings/string_util_impl_helpers.h b/naiveproxy/src/base/strings/string_util_impl_helpers.h index e328fdd1c3..8c264dd09e 100644 --- a/naiveproxy/src/base/strings/string_util_impl_helpers.h +++ b/naiveproxy/src/base/strings/string_util_impl_helpers.h @@ -481,7 +481,7 @@ static std::basic_string JoinStringT(list_type parts, T sep) { result.reserve(total_size); auto iter = parts.begin(); - DCHECK(iter != parts.end()); + CHECK(iter != parts.end(), base::NotFatalUntil::M125); result.append(*iter); ++iter; diff --git a/naiveproxy/src/base/sync_socket_nacl.cc b/naiveproxy/src/base/sync_socket_nacl.cc index 2d09942427..1de65dc71b 100644 --- a/naiveproxy/src/base/sync_socket_nacl.cc +++ b/naiveproxy/src/base/sync_socket_nacl.cc @@ -12,7 +12,7 @@ #include #include "base/containers/span.h" -#include "base/notreached.h" +#include "base/notimplemented.h" namespace base { diff --git a/naiveproxy/src/base/sync_socket_win.cc b/naiveproxy/src/base/sync_socket_win.cc index a92cc5d071..defc8aa092 100644 --- a/naiveproxy/src/base/sync_socket_win.cc +++ b/naiveproxy/src/base/sync_socket_win.cc @@ -11,6 +11,7 @@ #include "base/containers/span.h" #include "base/logging.h" +#include "base/notimplemented.h" #include "base/notreached.h" #include "base/rand_util.h" #include "base/threading/scoped_blocking_call.h" diff --git a/naiveproxy/src/base/synchronization/lock_impl.h b/naiveproxy/src/base/synchronization/lock_impl.h index f3a57fe8c5..c8aefa2ee9 100644 --- a/naiveproxy/src/base/synchronization/lock_impl.h +++ b/naiveproxy/src/base/synchronization/lock_impl.h @@ -8,8 +8,7 @@ #include "base/base_export.h" #include "base/check.h" #include "base/dcheck_is_on.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/raw_ref.h" +#include "base/memory/raw_ptr_exclusion.h" #include "base/thread_annotations.h" #include "build/build_config.h" @@ -136,25 +135,26 @@ class SCOPED_LOCKABLE BasicAutoLock { explicit BasicAutoLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) { - lock_->Acquire(); + lock_.Acquire(); } BasicAutoLock(LockType& lock, const AlreadyAcquired&) EXCLUSIVE_LOCKS_REQUIRED(lock) : lock_(lock) { - lock_->AssertAcquired(); + lock_.AssertAcquired(); } BasicAutoLock(const BasicAutoLock&) = delete; BasicAutoLock& operator=(const BasicAutoLock&) = delete; ~BasicAutoLock() UNLOCK_FUNCTION() { - lock_->AssertAcquired(); - lock_->Release(); + lock_.AssertAcquired(); + lock_.Release(); } private: - const raw_ref lock_; + // RAW_PTR_EXCLUSION: crbug.com/1521343 crbug.com/1520734 crbug.com/1519816 + RAW_PTR_EXCLUSION LockType& lock_; }; // This is an implementation used for AutoTryLock templated on the lock type. @@ -162,22 +162,23 @@ template class SCOPED_LOCKABLE BasicAutoTryLock { public: explicit BasicAutoTryLock(LockType& lock) EXCLUSIVE_LOCK_FUNCTION(lock) - : lock_(lock), is_acquired_(lock_->Try()) {} + : lock_(lock), is_acquired_(lock_.Try()) {} BasicAutoTryLock(const BasicAutoTryLock&) = delete; BasicAutoTryLock& operator=(const BasicAutoTryLock&) = delete; ~BasicAutoTryLock() UNLOCK_FUNCTION() { if (is_acquired_) { - lock_->AssertAcquired(); - lock_->Release(); + lock_.AssertAcquired(); + lock_.Release(); } } bool is_acquired() const { return is_acquired_; } private: - const raw_ref lock_; + // RAW_PTR_EXCLUSION: crbug.com/1521343 crbug.com/1520734 crbug.com/1519816 + RAW_PTR_EXCLUSION LockType& lock_; const bool is_acquired_; }; @@ -187,17 +188,18 @@ class BasicAutoUnlock { public: explicit BasicAutoUnlock(LockType& lock) : lock_(lock) { // We require our caller to have the lock. - lock_->AssertAcquired(); - lock_->Release(); + lock_.AssertAcquired(); + lock_.Release(); } BasicAutoUnlock(const BasicAutoUnlock&) = delete; BasicAutoUnlock& operator=(const BasicAutoUnlock&) = delete; - ~BasicAutoUnlock() { lock_->Acquire(); } + ~BasicAutoUnlock() { lock_.Acquire(); } private: - const raw_ref lock_; + // RAW_PTR_EXCLUSION: crbug.com/1521343 crbug.com/1520734 crbug.com/1519816 + RAW_PTR_EXCLUSION LockType& lock_; }; // This is an implementation used for AutoLockMaybe templated on the lock type. @@ -221,7 +223,8 @@ class SCOPED_LOCKABLE BasicAutoLockMaybe { } private: - const raw_ptr lock_; + // RAW_PTR_EXCLUSION: crbug.com/1521343 crbug.com/1520734 crbug.com/1519816 + RAW_PTR_EXCLUSION LockType* const lock_; }; // This is an implementation used for ReleasableAutoLock templated on the lock @@ -253,7 +256,8 @@ class SCOPED_LOCKABLE BasicReleasableAutoLock { } private: - raw_ptr lock_; + // RAW_PTR_EXCLUSION: crbug.com/1521343 crbug.com/1520734 crbug.com/1519816 + RAW_PTR_EXCLUSION LockType* lock_; }; } // namespace internal diff --git a/naiveproxy/src/base/synchronization/waitable_event.cc b/naiveproxy/src/base/synchronization/waitable_event.cc index 643ead3f05..b5a0226682 100644 --- a/naiveproxy/src/base/synchronization/waitable_event.cc +++ b/naiveproxy/src/base/synchronization/waitable_event.cc @@ -13,7 +13,7 @@ void WaitableEvent::Signal() { // Must be ordered before SignalImpl() to guarantee it's emitted before the // matching TerminatingFlow in TimedWait(). if (!only_used_while_idle_) { - TRACE_EVENT_INSTANT("wakeup.flow", "WaitableEvent::Signal", + TRACE_EVENT_INSTANT("wakeup.flow,toplevel.flow", "WaitableEvent::Signal", perfetto::Flow::FromPointer(this)); } SignalImpl(); @@ -39,7 +39,8 @@ bool WaitableEvent::TimedWait(TimeDelta wait_delta) { const bool result = TimedWaitImpl(wait_delta); if (result && !only_used_while_idle_) { - TRACE_EVENT_INSTANT("wakeup.flow", "WaitableEvent::Wait Complete", + TRACE_EVENT_INSTANT("wakeup.flow,toplevel.flow", + "WaitableEvent::Wait Complete", perfetto::TerminatingFlow::FromPointer(this)); } diff --git a/naiveproxy/src/base/synchronization/waitable_event_win.cc b/naiveproxy/src/base/synchronization/waitable_event_win.cc index 611e252903..5d4f1f6b9b 100644 --- a/naiveproxy/src/base/synchronization/waitable_event_win.cc +++ b/naiveproxy/src/base/synchronization/waitable_event_win.cc @@ -11,6 +11,9 @@ #include #include +#include "base/compiler_specific.h" +#include "base/debug/alias.h" +#include "base/debug/dump_without_crashing.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/threading/scoped_blocking_call.h" @@ -21,6 +24,15 @@ namespace base { +namespace { +NOINLINE void ReportInvalidWaitableEventResult(DWORD result) { + const auto last_error = ::GetLastError(); + base::debug::Alias(&last_error); + base::debug::Alias(&result); + base::debug::DumpWithoutCrashing(); // https://crbug.com/1478972. +} +} // namespace + WaitableEvent::WaitableEvent(ResetPolicy reset_policy, InitialState initial_state) : handle_(CreateEvent(nullptr, @@ -49,8 +61,9 @@ void WaitableEvent::SignalImpl() { bool WaitableEvent::IsSignaled() { DWORD result = WaitForSingleObject(handle_.get(), 0); - DCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) - << "Unexpected WaitForSingleObject result " << result; + if (result != WAIT_OBJECT_0 && result != WAIT_TIMEOUT) { + ReportInvalidWaitableEventResult(result); + } return result == WAIT_OBJECT_0; } @@ -72,17 +85,28 @@ bool WaitableEvent::TimedWaitImpl(TimeDelta wait_delta) { ? INFINITE : saturated_cast(remaining.InMillisecondsRoundedUp()); const DWORD result = WaitForSingleObject(handle_.get(), timeout_ms); - DPCHECK(result == WAIT_OBJECT_0 || result == WAIT_TIMEOUT) - << "Unexpected WaitForSingleObject result " << result; - switch (result) { - case WAIT_OBJECT_0: - return true; - case WAIT_TIMEOUT: - // TimedWait can time out earlier than the specified |timeout| on - // Windows. To make this consistent with the posix implementation we - // should guarantee that TimedWait doesn't return earlier than the - // specified |max_time| and wait again for the remaining time. - continue; + if (result == WAIT_OBJECT_0) { + // The object is signaled. + return true; + } + + if (result == WAIT_TIMEOUT) { + // TimedWait can time out earlier than the specified |timeout| on + // Windows. To make this consistent with the posix implementation we + // should guarantee that TimedWait doesn't return earlier than the + // specified |max_time| and wait again for the remaining time. + continue; + } + + // The only other documented result values are `WAIT_ABANDONED` and + // `WAIT_FAILED`. Neither of these nor any other result should ever be + // emitted unless there is a double free or another entity is tampering + // with this instance's event handle. Only fails if the timeout was + // INFINITE. + if (wait_delta.is_max()) { + ReportInvalidWaitableEventResult(result); + // The code may infinite loop and then hang if the returned value + // continues being `WAIT_FAILED`. } } return false; diff --git a/naiveproxy/src/base/sys_byteorder.h b/naiveproxy/src/base/sys_byteorder.h index 5aa8980247..70c88a05f6 100644 --- a/naiveproxy/src/base/sys_byteorder.h +++ b/naiveproxy/src/base/sys_byteorder.h @@ -13,112 +13,80 @@ #include +#include "base/numerics/byte_conversions.h" #include "build/build_config.h" #if defined(COMPILER_MSVC) #include #endif -#if defined(COMPILER_MSVC) && !defined(__clang__) -// TODO(pkasting): See -// https://developercommunity.visualstudio.com/t/Mark-some-built-in-functions-as-constexp/362558 -// https://developercommunity.visualstudio.com/t/constexpr-byte-swapping-optimization/983963 -#define BASE_BYTESWAPS_CONSTEXPR -#else -#define BASE_BYTESWAPS_CONSTEXPR constexpr -#endif - namespace base { // Returns a value with all bytes in |x| swapped, i.e. reverses the endianness. -// TODO(pkasting): Once C++23 is available, replace with std::byteswap. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwap(uint16_t x) { -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_ushort(x); -#else - return __builtin_bswap16(x); -#endif +// TODO(danakj): Replace with base::numerics::byteswap(). +inline constexpr uint16_t ByteSwap(uint16_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwap(uint32_t x) { -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_ulong(x); -#else - return __builtin_bswap32(x); -#endif +inline constexpr uint32_t ByteSwap(uint32_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwap(uint64_t x) { - // Per build/build_config.h, clang masquerades as MSVC on Windows. If we are - // actually using clang, we can rely on the builtin. - // - // This matters in practice, because on x86(_64), this is a single "bswap" - // instruction. MSVC correctly replaces the call with an inlined bswap at /O2 - // as of 2021, but clang as we use it in Chromium doesn't, keeping a function - // call for a single instruction. -#if defined(COMPILER_MSVC) && !defined(__clang__) - return _byteswap_uint64(x); -#else - return __builtin_bswap64(x); -#endif +inline constexpr uint64_t ByteSwap(uint64_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } -inline BASE_BYTESWAPS_CONSTEXPR uintptr_t ByteSwapUintPtrT(uintptr_t x) { - // We do it this way because some build configurations are ILP32 even when - // defined(ARCH_CPU_64_BITS). Unfortunately, we can't use sizeof in #ifs. But, - // because these conditionals are constexprs, the irrelevant branches will - // likely be optimized away, so this construction should not result in code - // bloat. - static_assert(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8, - "Unsupported uintptr_t size"); - if (sizeof(uintptr_t) == 4) - return ByteSwap(static_cast(x)); - return ByteSwap(static_cast(x)); +inline constexpr uintptr_t ByteSwapUintPtrT(uintptr_t x) { + // Forward to templated function in //base/numerics. + return numerics::ByteSwap(x); } // Converts the bytes in |x| from host order (endianness) to little endian, and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t ByteSwapToLE16(uint16_t x) { +inline constexpr uint16_t ByteSwapToLE16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t ByteSwapToLE32(uint32_t x) { +inline constexpr uint32_t ByteSwapToLE32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t ByteSwapToLE64(uint64_t x) { +inline constexpr uint64_t ByteSwapToLE64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) return x; #else - return ByteSwap(x); + return numerics::ByteSwap(x); #endif } // Converts the bytes in |x| from network to host order (endianness), and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t NetToHost16(uint16_t x) { +inline constexpr uint16_t NetToHost16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t NetToHost32(uint32_t x) { +inline constexpr uint32_t NetToHost32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t NetToHost64(uint64_t x) { +inline constexpr uint64_t NetToHost64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif @@ -126,23 +94,23 @@ inline BASE_BYTESWAPS_CONSTEXPR uint64_t NetToHost64(uint64_t x) { // Converts the bytes in |x| from host to network order (endianness), and // returns the result. -inline BASE_BYTESWAPS_CONSTEXPR uint16_t HostToNet16(uint16_t x) { +inline constexpr uint16_t HostToNet16(uint16_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint32_t HostToNet32(uint32_t x) { +inline constexpr uint32_t HostToNet32(uint32_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif } -inline BASE_BYTESWAPS_CONSTEXPR uint64_t HostToNet64(uint64_t x) { +inline constexpr uint64_t HostToNet64(uint64_t x) { #if defined(ARCH_CPU_LITTLE_ENDIAN) - return ByteSwap(x); + return numerics::ByteSwap(x); #else return x; #endif @@ -150,6 +118,6 @@ inline BASE_BYTESWAPS_CONSTEXPR uint64_t HostToNet64(uint64_t x) { } // namespace base -#undef BASE_BYTESWAPS_CONSTEXPR +#undef constexpr #endif // BASE_SYS_BYTEORDER_H_ diff --git a/naiveproxy/src/base/syslog_logging.cc b/naiveproxy/src/base/syslog_logging.cc index 48ffbc2b01..e27df0ff0a 100644 --- a/naiveproxy/src/base/syslog_logging.cc +++ b/naiveproxy/src/base/syslog_logging.cc @@ -7,7 +7,9 @@ #include "build/build_config.h" #if BUILDFLAG(IS_WIN) -#include +// clang-format off +#include // Must be in front of other Windows header files. +// clang-format on #include diff --git a/naiveproxy/src/base/system/sys_info_fuchsia.cc b/naiveproxy/src/base/system/sys_info_fuchsia.cc index 92bc1df36a..d722f257c1 100644 --- a/naiveproxy/src/base/system/sys_info_fuchsia.cc +++ b/naiveproxy/src/base/system/sys_info_fuchsia.cc @@ -17,6 +17,7 @@ #include "base/fuchsia/system_info.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/notimplemented.h" #include "base/numerics/clamped_math.h" #include "base/strings/string_piece.h" #include "base/synchronization/lock.h" diff --git a/naiveproxy/src/base/system/sys_info_mac.mm b/naiveproxy/src/base/system/sys_info_mac.mm index 96c262aa85..60ead0cf5b 100644 --- a/naiveproxy/src/base/system/sys_info_mac.mm +++ b/naiveproxy/src/base/system/sys_info_mac.mm @@ -157,14 +157,12 @@ SysInfo::SplitHardwareModelNameDoNotUse(std::string_view name) { } HardwareModelNameSplit split; - const auto* begin = name.begin(); - if (!StringToInt(std::string_view(begin + number_loc, begin + comma_loc), + if (!StringToInt(name.substr(0u, comma_loc).substr(number_loc), &split.model) || - !StringToInt(std::string_view(begin + comma_loc + 1, name.end()), - &split.variant)) { + !StringToInt(name.substr(comma_loc + 1), &split.variant)) { return absl::nullopt; } - split.category = name.substr(0, number_loc); + split.category = name.substr(0u, number_loc); return split; } diff --git a/naiveproxy/src/base/system/sys_info_posix.cc b/naiveproxy/src/base/system/sys_info_posix.cc index 4482b59b7d..69cf95c169 100644 --- a/naiveproxy/src/base/system/sys_info_posix.cc +++ b/naiveproxy/src/base/system/sys_info_posix.cc @@ -19,6 +19,7 @@ #include "base/check.h" #include "base/files/file_util.h" #include "base/lazy_instance.h" +#include "base/notimplemented.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" diff --git a/naiveproxy/src/base/task/common/checked_lock_impl.cc b/naiveproxy/src/base/task/common/checked_lock_impl.cc index 87c7509e92..32af08bc8f 100644 --- a/naiveproxy/src/base/task/common/checked_lock_impl.cc +++ b/naiveproxy/src/base/task/common/checked_lock_impl.cc @@ -50,7 +50,7 @@ class SafeAcquisitionTracker { void RecordRelease(const CheckedLockImpl* const lock) { LockVector* acquired_locks = GetAcquiredLocksOnCurrentThread(); const auto iter_at_lock = ranges::find(*acquired_locks, lock); - DCHECK(iter_at_lock != acquired_locks->end()); + CHECK(iter_at_lock != acquired_locks->end(), base::NotFatalUntil::M125); acquired_locks->erase(iter_at_lock); } diff --git a/naiveproxy/src/base/task/common/task_annotator.cc b/naiveproxy/src/base/task/common/task_annotator.cc index 4c2ab37e1e..faa8e8fd23 100644 --- a/naiveproxy/src/base/task/common/task_annotator.cc +++ b/naiveproxy/src/base/task/common/task_annotator.cc @@ -11,6 +11,7 @@ #include "base/auto_reset.h" #include "base/check_op.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/debug/alias.h" #include "base/hash/md5.h" #include "base/logging.h" @@ -314,7 +315,7 @@ TaskAnnotator::ScopedSetIpcHash::ScopedSetIpcHash( uint32_t TaskAnnotator::ScopedSetIpcHash::MD5HashMetricName( base::StringPiece name) { base::MD5Digest digest; - base::MD5Sum(name.data(), name.size(), &digest); + base::MD5Sum(base::as_byte_span(name), &digest); uint32_t value; DCHECK_GE(sizeof(digest.a), sizeof(value)); memcpy(&value, digest.a, sizeof(value)); diff --git a/naiveproxy/src/base/task/post_job.cc b/naiveproxy/src/base/task/post_job.cc index 1ed3baad0f..69fa3190c8 100644 --- a/naiveproxy/src/base/task/post_job.cc +++ b/naiveproxy/src/base/task/post_job.cc @@ -4,11 +4,8 @@ #include "base/task/post_job.h" -#include "base/feature_list.h" #include "base/task/scoped_set_task_priority_for_current_thread.h" -#include "base/task/task_features.h" #include "base/task/thread_pool/job_task_source.h" -#include "base/task/thread_pool/job_task_source_old.h" #include "base/task/thread_pool/pooled_task_runner_delegate.h" #include "base/task/thread_pool/thread_pool_impl.h" #include "base/task/thread_pool/thread_pool_instance.h" @@ -26,7 +23,7 @@ scoped_refptr CreateJobTaskSource( << "Hint: if this is in a unit test, you're likely merely missing a " "base::test::TaskEnvironment member in your fixture.\n"; - return internal::CreateJobTaskSource( + return base::MakeRefCounted( from_here, traits, std::move(worker_task), std::move(max_concurrency_callback), static_cast(ThreadPoolInstance::Get())); @@ -104,15 +101,15 @@ bool JobHandle::IsActive() const { void JobHandle::UpdatePriority(TaskPriority new_priority) { if (!internal::PooledTaskRunnerDelegate::MatchesCurrentDelegate( - task_source_->GetDelegate())) { + task_source_->delegate())) { return; } - task_source_->GetDelegate()->UpdateJobPriority(task_source_, new_priority); + task_source_->delegate()->UpdateJobPriority(task_source_, new_priority); } void JobHandle::NotifyConcurrencyIncrease() { if (!internal::PooledTaskRunnerDelegate::MatchesCurrentDelegate( - task_source_->GetDelegate())) { + task_source_->delegate())) { return; } task_source_->NotifyConcurrencyIncrease(); @@ -120,35 +117,36 @@ void JobHandle::NotifyConcurrencyIncrease() { void JobHandle::Join() { DCHECK(internal::PooledTaskRunnerDelegate::MatchesCurrentDelegate( - task_source_->GetDelegate())); + task_source_->delegate())); DCHECK_GE(internal::GetTaskPriorityForCurrentThread(), task_source_->priority_racy()) << "Join may not be called on Job with higher priority than the current " "thread."; UpdatePriority(internal::GetTaskPriorityForCurrentThread()); - - // Ensure that the job is queued if it has remaining concurrency. This is - // necessary to support CreateJob(...).Join(). - task_source_->NotifyConcurrencyIncrease(); - + if (task_source_->GetRemainingConcurrency() != 0) { + // Make sure the task source is in the queue if not enough workers are + // contributing. This is necessary for CreateJob(...).Join(). This is a + // noop if the task source was already in the queue. + task_source_->delegate()->EnqueueJobTaskSource(task_source_); + } bool must_run = task_source_->WillJoin(); while (must_run) must_run = task_source_->RunJoinTask(); // Remove |task_source_| from the ThreadPool to prevent access to // |max_concurrency_callback| after Join(). - task_source_->GetDelegate()->RemoveJobTaskSource(task_source_); + task_source_->delegate()->RemoveJobTaskSource(task_source_); task_source_ = nullptr; } void JobHandle::Cancel() { DCHECK(internal::PooledTaskRunnerDelegate::MatchesCurrentDelegate( - task_source_->GetDelegate())); + task_source_->delegate())); task_source_->Cancel(); bool must_run = task_source_->WillJoin(); DCHECK(!must_run); // Remove |task_source_| from the ThreadPool to prevent access to // |max_concurrency_callback| after Join(). - task_source_->GetDelegate()->RemoveJobTaskSource(task_source_); + task_source_->delegate()->RemoveJobTaskSource(task_source_); task_source_ = nullptr; } @@ -169,8 +167,13 @@ JobHandle PostJob(const Location& from_here, auto task_source = CreateJobTaskSource(from_here, traits, std::move(worker_task), std::move(max_concurrency_callback)); - task_source->NotifyConcurrencyIncrease(); - return internal::JobTaskSource::CreateJobHandle(std::move(task_source)); + const bool queued = + static_cast(ThreadPoolInstance::Get()) + ->EnqueueJobTaskSource(task_source); + if (queued) { + return internal::JobTaskSource::CreateJobHandle(std::move(task_source)); + } + return JobHandle(); } JobHandle CreateJob(const Location& from_here, @@ -183,25 +186,4 @@ JobHandle CreateJob(const Location& from_here, return internal::JobTaskSource::CreateJobHandle(std::move(task_source)); } -namespace internal { - -scoped_refptr CreateJobTaskSource( - const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate) { - if (base::FeatureList::IsEnabled(kUseNewJobImplementation)) { - return base::MakeRefCounted( - from_here, traits, std::move(worker_task), - std::move(max_concurrency_callback), delegate); - } - - return base::MakeRefCounted( - from_here, traits, std::move(worker_task), - std::move(max_concurrency_callback), delegate); -} - -} // namespace internal - } // namespace base diff --git a/naiveproxy/src/base/task/post_job.h b/naiveproxy/src/base/task/post_job.h index f64230bf89..582aa61eda 100644 --- a/naiveproxy/src/base/task/post_job.h +++ b/naiveproxy/src/base/task/post_job.h @@ -207,19 +207,6 @@ CreateJob(const Location& from_here, RepeatingCallback worker_task, MaxConcurrencyCallback max_concurrency_callback); -namespace internal { - -// Helper which creates a JobTaskSourceNew or JobTaskSourceOld depending on the -// UseNewJobImplementation feature. Exposed for testing. -scoped_refptr BASE_EXPORT -CreateJobTaskSource(const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate); - -} // namespace internal - } // namespace base #endif // BASE_TASK_POST_JOB_H_ diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc index 142bbad2ed..536b4f6738 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.cc @@ -1002,8 +1002,10 @@ Value::Dict SequenceManagerImpl::AsValueWithSelectorResult( TimeTicks now = NowTicks(); Value::Dict state; Value::List active_queues; - for (auto* const queue : main_thread_only().active_queues) + for (internal::TaskQueueImpl* const queue : + main_thread_only().active_queues) { active_queues.Append(queue->AsValue(now, force_verbose)); + } state.Set("active_queues", std::move(active_queues)); Value::List shutdown_queues; Value::List queues_to_delete; @@ -1054,7 +1056,7 @@ void SequenceManagerImpl::ReclaimMemory() { LazyNow lazy_now(main_thread_clock()); for (auto it = main_thread_only().active_queues.begin(); it != main_thread_only().active_queues.end();) { - auto* const queue = *it++; + auto* const queue = (*it++).get(); ReclaimMemoryFromQueue(queue, &lazy_now); } } diff --git a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h index 8ed882bd3b..005129d1ab 100644 --- a/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h +++ b/naiveproxy/src/base/task/sequence_manager/sequence_manager_impl.h @@ -156,10 +156,11 @@ class BASE_EXPORT SequenceManagerImpl CurrentThread::DestructionObserver* destruction_observer); [[nodiscard]] CallbackListSubscription RegisterOnNextIdleCallback( OnceClosure on_next_idle_callback); - // TODO(alexclarke): Remove this as part of https://crbug.com/825327. + + // Sets / returns the default TaskRunner. Thread-safe. void SetTaskRunner(scoped_refptr task_runner); - // TODO(alexclarke): Remove this as part of https://crbug.com/825327. scoped_refptr GetTaskRunner(); + bool IsBoundToCurrentThread() const; MessagePump* GetMessagePump() const; bool IsType(MessagePumpType type) const; @@ -327,7 +328,7 @@ class BASE_EXPORT SequenceManagerImpl // internal scheduling code does not expect queues to be pulled // from underneath. - std::set active_queues; + std::set> active_queues; std::map> queues_to_delete; diff --git a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc index cb18ba61b8..926aba0fb3 100644 --- a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc +++ b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.cc @@ -29,12 +29,12 @@ #include "base/task/sequence_manager/task_order.h" #include "base/task/sequence_manager/wake_up_queue.h" #include "base/task/sequence_manager/work_queue.h" +#include "base/task/single_thread_task_runner.h" #include "base/task/task_features.h" #include "base/task/task_observer.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" #include "base/trace_event/base_tracing.h" -#include "base/types/pass_key.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -44,6 +44,23 @@ namespace sequence_manager { namespace internal { +// This class outside the anonymous namespace exists to allow being a friend of +// `SingleThreadTaskRunner::CurrentDefaultHandle` in order to access +// `SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist`. +class CurrentDefaultHandleOverrideForRunOrPostTask { + public: + explicit CurrentDefaultHandleOverrideForRunOrPostTask( + scoped_refptr task_runner) + : sttr_override_( + nullptr, + SingleThreadTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}), + str_override_(std::move(task_runner)) {} + + private: + SingleThreadTaskRunner::CurrentDefaultHandle sttr_override_; + SequencedTaskRunner::CurrentDefaultHandle str_override_; +}; + namespace { // An atomic is used here because the value is queried from other threads when @@ -56,10 +73,14 @@ std::atomic_bool g_explicit_high_resolution_timer_win{true}; #endif // BUILDFLAG(IS_WIN) void RunTaskSynchronously(const AssociatedThreadId* associated_thread, + scoped_refptr task_runner, OnceClosure closure) { base::internal::TaskScope sequence_scope( associated_thread->GetBoundSequenceToken(), - /* is_thread_bound=*/false); + /* is_thread_bound=*/false, + /* is_running_synchronously=*/true); + CurrentDefaultHandleOverrideForRunOrPostTask task_runner_override( + std::move(task_runner)); std::move(closure).Run(); } @@ -114,6 +135,7 @@ bool TaskQueueImpl::GuardedTaskPoster::RunOrPostTask(PostedTask task) { // `IsQueueEnabledFromAnyThread()`. That won't prevent the task from running. if (sync_work_auth.IsValid() && outer_->IsQueueEnabledFromAnyThread()) { RunTaskSynchronously(outer_->associated_thread_.get(), + outer_->sequence_manager_->GetTaskRunner(), std::move(task.callback)); return true; } @@ -188,10 +210,28 @@ bool TaskQueueImpl::TaskRunner::RunOrPostTask(subtle::RunOrPostTaskPassKey, Nestable::kNestable, task_type_)); } -bool TaskQueueImpl::TaskRunner::RunsTasksInCurrentSequence() const { +bool TaskQueueImpl::TaskRunner::BelongsToCurrentThread() const { return associated_thread_->IsBoundToCurrentThread(); } +bool TaskQueueImpl::TaskRunner::RunsTasksInCurrentSequence() const { + // Return true on the bound thread. This works even after `thread_local` + // destruction. + if (BelongsToCurrentThread()) { + return true; + } + + // Return true in a `RunOrPostTask` callback running synchronously on a + // different thread. + if (associated_thread_->IsBound() && + associated_thread_->GetBoundSequenceToken() == + base::internal::SequenceToken::GetForCurrentThread()) { + return true; + } + + return false; +} + // static void TaskQueueImpl::InitializeFeatures() { g_max_precise_delay = kMaxPreciseDelay.Get(); @@ -1548,7 +1588,8 @@ void TaskQueueImpl::OnQueueEnabledVoteChanged(bool enabled) { } void TaskQueueImpl::CompleteInitializationOnBoundThread() { - voter_weak_ptr_factory_.BindToCurrentSequence(PassKey()); + voter_weak_ptr_factory_.BindToCurrentSequence( + subtle::BindWeakPtrFactoryPassKey()); } TaskQueue::QueuePriority TaskQueueImpl::DefaultPriority() const { diff --git a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h index abd306adcd..e835f29b4f 100644 --- a/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h +++ b/naiveproxy/src/base/task/sequence_manager/task_queue_impl.h @@ -347,6 +347,7 @@ class BASE_EXPORT TaskQueueImpl : public TaskQueue { bool RunOrPostTask(subtle::RunOrPostTaskPassKey, const Location& from_here, OnceClosure task) final; + bool BelongsToCurrentThread() const final; bool RunsTasksInCurrentSequence() const final; private: diff --git a/naiveproxy/src/base/task/sequence_manager/thread_controller_impl.h b/naiveproxy/src/base/task/sequence_manager/thread_controller_impl.h index 2ff4916f73..f8273118d1 100644 --- a/naiveproxy/src/base/task/sequence_manager/thread_controller_impl.h +++ b/naiveproxy/src/base/task/sequence_manager/thread_controller_impl.h @@ -78,10 +78,8 @@ class BASE_EXPORT ThreadControllerImpl : public ThreadController, scoped_refptr task_runner, const TickClock* time_source); - // TODO(altimin): Make these const. Blocked on removing - // lazy initialisation support. - raw_ptr funneled_sequence_manager_; - scoped_refptr task_runner_; + const raw_ptr funneled_sequence_manager_; + const scoped_refptr task_runner_; raw_ptr nesting_observer_ = nullptr; diff --git a/naiveproxy/src/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc b/naiveproxy/src/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc index 094d1ac3c7..d43fd5027a 100644 --- a/naiveproxy/src/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc +++ b/naiveproxy/src/base/task/sequence_manager/thread_controller_with_message_pump_impl.cc @@ -46,11 +46,6 @@ TimeTicks CapAtOneDay(TimeTicks next_run_time, LazyNow* lazy_now) { return std::min(next_run_time, lazy_now->Now() + Days(1)); } -// Feature to run tasks by batches before pumping out messages. -BASE_FEATURE(kRunTasksByBatches, - "RunTasksByBatches", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kAvoidScheduleWorkDuringNativeEventProcessing, "AvoidScheduleWorkDuringNativeEventProcessing", base::FEATURE_DISABLED_BY_DEFAULT); @@ -78,7 +73,7 @@ base::TimeDelta GetLeewayForWakeUp(absl::optional wake_up) { // static void ThreadControllerWithMessagePumpImpl::InitializeFeatures() { - g_run_tasks_by_batches.store(FeatureList::IsEnabled(kRunTasksByBatches), + g_run_tasks_by_batches.store(FeatureList::IsEnabled(base::kRunTasksByBatches), std::memory_order_relaxed); g_avoid_schedule_calls_during_native_event_processing.store( FeatureList::IsEnabled(kAvoidScheduleWorkDuringNativeEventProcessing), @@ -92,7 +87,7 @@ void ThreadControllerWithMessagePumpImpl::InitializeFeatures() { // static void ThreadControllerWithMessagePumpImpl::ResetFeatures() { g_run_tasks_by_batches.store( - kRunTasksByBatches.default_state == FEATURE_ENABLED_BY_DEFAULT, + base::kRunTasksByBatches.default_state == FEATURE_ENABLED_BY_DEFAULT, std::memory_order_relaxed); } diff --git a/naiveproxy/src/base/task/sequenced_task_runner.cc b/naiveproxy/src/base/task/sequenced_task_runner.cc index 572b1e8137..53a86189e7 100644 --- a/naiveproxy/src/base/task/sequenced_task_runner.cc +++ b/naiveproxy/src/base/task/sequenced_task_runner.cc @@ -86,7 +86,7 @@ bool SequencedTaskRunner::RunOrPostTask(subtle::RunOrPostTaskPassKey, // static const scoped_refptr& SequencedTaskRunner::GetCurrentDefault() { - CHECK(current_default_handle) + CHECK(HasCurrentDefault()) << "Error: This caller requires a sequenced context (i.e. the current " "task needs to run from a SequencedTaskRunner). If you're in a test " "refer to //docs/threading_and_tasks_testing.md."; @@ -95,19 +95,29 @@ SequencedTaskRunner::GetCurrentDefault() { // static bool SequencedTaskRunner::HasCurrentDefault() { - return !!current_default_handle; + return !!current_default_handle && !!current_default_handle->task_runner_; } SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle( scoped_refptr task_runner) - : resetter_(¤t_default_handle, this, nullptr), - task_runner_(std::move(task_runner)) { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); + : CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) { + CHECK(!previous_handle_ || !previous_handle_->task_runner_); } SequencedTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() { - DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK_EQ(current_default_handle, this); + current_default_handle = previous_handle_; +} + +SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle( + scoped_refptr task_runner, + MayAlreadyExist) + : task_runner_(std::move(task_runner)), + previous_handle_(current_default_handle) { + // Support overriding the current default with a null task runner or a task + // runner that runs its tasks in the current sequence. + DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence()); + current_default_handle = this; } bool SequencedTaskRunner::DeleteOrReleaseSoonInternal( diff --git a/naiveproxy/src/base/task/sequenced_task_runner.h b/naiveproxy/src/base/task/sequenced_task_runner.h index 5d3d136db5..6d92c6f4e6 100644 --- a/naiveproxy/src/base/task/sequenced_task_runner.h +++ b/naiveproxy/src/base/task/sequenced_task_runner.h @@ -10,6 +10,7 @@ #include "base/auto_reset.h" #include "base/base_export.h" #include "base/functional/callback.h" +#include "base/gtest_prod_util.h" #include "base/task/delay_policy.h" #include "base/task/delayed_task_handle.h" #include "base/task/sequenced_task_runner_helpers.h" @@ -36,13 +37,16 @@ class ThreadWrapper; namespace base { +namespace android { +class PreFreezeBackgroundMemoryTrimmer; +} namespace internal { class DelayTimerBase; class DelayedTaskManager; } class DeadlineTimer; class MetronomeTimer; -class PreFreezeBackgroundMemoryTrimmer; +class SingleThreadTaskRunner; class TimeDelta; class TimeTicks; @@ -68,7 +72,7 @@ class PostDelayedTaskPassKey { friend class media::AlsaPcmInputStream; friend class media::FakeAudioWorker; #if BUILDFLAG(IS_ANDROID) - friend class base::PreFreezeBackgroundMemoryTrimmer; + friend class base::android::PreFreezeBackgroundMemoryTrimmer; #endif }; @@ -244,7 +248,7 @@ class BASE_EXPORT SequencedTaskRunner : public TaskRunner { // appropriate to invoke this if `task` may take a long time to run. // // TODO(crbug.com/1503967): This API is still in development. It doesn't yet - // support SEQUENCE_CHECKER or SequenceLocalStorage. + // support SequenceLocalStorage. virtual bool RunOrPostTask(subtle::RunOrPostTaskPassKey, const Location& from_here, OnceClosure task); @@ -330,9 +334,10 @@ class BASE_EXPORT SequencedTaskRunner : public TaskRunner { class BASE_EXPORT CurrentDefaultHandle { public: - // Binds `task_runner` to the current thread so that it is returned by - // GetCurrentDefault() in the scope of the constructed - // `CurrentDefaultHandle`. + // Sets the value returned by `SequencedTaskRunner::GetCurrentDefault()` to + // `task_runner` within its scope. `task_runner` must belong to the current + // sequence. There must not already be a current default + // `SequencedTaskRunner` on this thread. explicit CurrentDefaultHandle( scoped_refptr task_runner); @@ -343,24 +348,32 @@ class BASE_EXPORT SequencedTaskRunner : public TaskRunner { private: friend class SequencedTaskRunner; - friend class CurrentHandleOverride; - const AutoReset resetter_; + // Overriding an existing current default SingleThreadTaskRunner should only + // be needed under special circumstances. Require them to be enumerated as + // friends to require //base/OWNERS review. Use + // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to + // avoid the friend requirement. + friend class SingleThreadTaskRunner; + FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest, + OverrideWithNull); + FRIEND_TEST_ALL_PREFIXES(SequencedTaskRunnerCurrentDefaultHandleTest, + OverrideWithNonNull); + + struct MayAlreadyExist {}; + + // Same as the public constructor, but there may already be a current + // default `SequencedTaskRunner` on this thread. + CurrentDefaultHandle(scoped_refptr task_runner, + MayAlreadyExist); scoped_refptr task_runner_; + raw_ptr previous_handle_; }; protected: ~SequencedTaskRunner() override = default; - // Helper to allow SingleThreadTaskRunner::CurrentDefaultHandle to double as a - // SequencedTaskRunner::CurrentDefaultHandle. - static void SetCurrentDefaultHandleTaskRunner( - CurrentDefaultHandle& current_default, - scoped_refptr task_runner) { - current_default.task_runner_ = task_runner; - } - virtual bool DeleteOrReleaseSoonInternal(const Location& from_here, void (*deleter)(const void*), const void* object); diff --git a/naiveproxy/src/base/task/single_thread_task_runner.cc b/naiveproxy/src/base/task/single_thread_task_runner.cc index 2b0ea0fe8e..3eba23f647 100644 --- a/naiveproxy/src/base/task/single_thread_task_runner.cc +++ b/naiveproxy/src/base/task/single_thread_task_runner.cc @@ -37,11 +37,15 @@ SingleThreadTaskRunner::CurrentDefaultHandle* GetCurrentDefaultHandle() { } // namespace +bool SingleThreadTaskRunner::BelongsToCurrentThread() const { + return RunsTasksInCurrentSequence(); +} + // static const scoped_refptr& SingleThreadTaskRunner::GetCurrentDefault() { const auto* const handle = GetCurrentDefaultHandle(); - CHECK(handle) + CHECK(handle && handle->task_runner_) << "Error: This caller requires a single-threaded context (i.e. the " "current task needs to run from a SingleThreadTaskRunner). If you're " "in a test refer to //docs/threading_and_tasks_testing.md." @@ -56,71 +60,44 @@ SingleThreadTaskRunner::GetCurrentDefault() { // static bool SingleThreadTaskRunner::HasCurrentDefault() { - return !!GetCurrentDefaultHandle(); + return !!GetCurrentDefaultHandle() && + !!GetCurrentDefaultHandle()->task_runner_; } SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle( scoped_refptr task_runner) - : resetter_(¤t_default_handle, this, nullptr), - task_runner_(std::move(task_runner)), - sequenced_task_runner_current_default_(task_runner_) { - DCHECK(task_runner_->BelongsToCurrentThread()); + : CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) { + CHECK(!previous_handle_ || !previous_handle_->task_runner_); } SingleThreadTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() { - DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK_EQ(GetCurrentDefaultHandle(), this); + current_default_handle = previous_handle_; } -SingleThreadTaskRunner::CurrentHandleOverride::CurrentHandleOverride( - scoped_refptr overriding_task_runner, - bool allow_nested_runloop) { - DCHECK(!SequencedTaskRunner::HasCurrentDefault() || - SingleThreadTaskRunner::HasCurrentDefault()) - << "SingleThreadTaskRunner::CurrentHandleOverride is not compatible with " - "a SequencedTaskRunner::CurrentDefaultHandle already " - "being set on this thread (except when it's " - "set by the current " - "SingleThreadTaskRunner::CurrentDefaultHandle)."; - - if (!SingleThreadTaskRunner::HasCurrentDefault()) { - top_level_thread_task_runner_current_default_.emplace( - std::move(overriding_task_runner)); - return; - } - -#if DCHECK_IS_ON() - expected_task_runner_before_restore_ = overriding_task_runner.get(); -#endif - auto* const handle = GetCurrentDefaultHandle(); - SequencedTaskRunner::SetCurrentDefaultHandleTaskRunner( - handle->sequenced_task_runner_current_default_, overriding_task_runner); - handle->task_runner_.swap(overriding_task_runner); - // Due to the swap, now `handle->task_runner_` points to the overriding task - // runner and `overriding_task_runner_` points to the previous task runner. - task_runner_to_restore_ = std::move(overriding_task_runner); - - if (!allow_nested_runloop) { - no_running_during_override_ = - std::make_unique(); - } +SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle( + scoped_refptr task_runner, + MayAlreadyExist) + : task_runner_(std::move(task_runner)), + previous_handle_(GetCurrentDefaultHandle()), + sequenced_handle_( + task_runner_, + SequencedTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}) { + // Support overriding the current default with a null task runner or a task + // runner that belongs to the current thread. + DCHECK(!task_runner_ || task_runner_->BelongsToCurrentThread()); + current_default_handle = this; } -SingleThreadTaskRunner::CurrentHandleOverride::~CurrentHandleOverride() { - if (task_runner_to_restore_) { - auto* const handle = GetCurrentDefaultHandle(); -#if DCHECK_IS_ON() - DCHECK_EQ(expected_task_runner_before_restore_, handle->task_runner_.get()) - << "Nested overrides must expire their " - "SingleThreadTaskRunner::CurrentHandleOverride " - "in LIFO order."; -#endif +SingleThreadTaskRunner::CurrentHandleOverrideForTesting:: + CurrentHandleOverrideForTesting( + scoped_refptr overriding_task_runner) + : current_default_handle_(std::move(overriding_task_runner), + CurrentDefaultHandle::MayAlreadyExist{}), + no_running_during_override_( + std::make_unique()) {} - SequencedTaskRunner::SetCurrentDefaultHandleTaskRunner( - handle->sequenced_task_runner_current_default_, - task_runner_to_restore_); - handle->task_runner_.swap(task_runner_to_restore_); - } -} +SingleThreadTaskRunner::CurrentHandleOverrideForTesting:: + ~CurrentHandleOverrideForTesting() = default; } // namespace base diff --git a/naiveproxy/src/base/task/single_thread_task_runner.h b/naiveproxy/src/base/task/single_thread_task_runner.h index 24b060d4ea..2f1d4b55f0 100644 --- a/naiveproxy/src/base/task/single_thread_task_runner.h +++ b/naiveproxy/src/base/task/single_thread_task_runner.h @@ -17,6 +17,10 @@ namespace blink::scheduler { class MainThreadSchedulerImpl; } // namespace blink::scheduler +namespace base::sequence_manager::internal { +class CurrentDefaultHandleOverrideForRunOrPostTask; +} + namespace base { class ScopedDisallowRunningRunLoop; @@ -35,8 +39,13 @@ class ScopedDisallowRunningRunLoop; // running other kinds of message loop, e.g. Jingle threads. class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { public: - // A more explicit alias to RunsTasksInCurrentSequence(). - bool BelongsToCurrentThread() const { return RunsTasksInCurrentSequence(); } + // Returns true if the `SingleThreadTaskRunner` runs tasks posted to it on the + // current thread. + // + // Identical to `RunsTaskInCurrentSequence()`, except from a `RunOrPostTask()` + // callback running synchronously (in that case, `BelongsToCurrentThread()` + // returns false and `RunsTaskInCurrentSequence()` returns true). + virtual bool BelongsToCurrentThread() const; // Returns the default SingleThreadTaskRunner for the current thread. // On threads that service multiple task queues, the default task queue is @@ -60,13 +69,14 @@ class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { // the current thread. [[nodiscard]] static bool HasCurrentDefault(); - class CurrentHandleOverride; class CurrentHandleOverrideForTesting; class BASE_EXPORT CurrentDefaultHandle { public: - // Binds |task_runner| to the current thread. |task_runner| must belong - // to the current thread. + // Sets the value returned by `SingleThreadTaskRunner::GetCurrentDefault()` + // and `SequencedTaskRunner::GetCurrentDefault()` to `task_runner` within + // its scope. `task_runner` must belong to the current thread. There must + // not already be a current default `SingleThreadTaskRunner` on this thread. explicit CurrentDefaultHandle( scoped_refptr task_runner); @@ -77,87 +87,54 @@ class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner { private: friend class SingleThreadTaskRunner; - friend class CurrentHandleOverride; - const AutoReset resetter_; - - scoped_refptr task_runner_; - - // Registers |task_runner_|'s SequencedTaskRunner interface as the - // SequencedTaskRunner::CurrentDefaultHandle on this thread. - SequencedTaskRunner::CurrentDefaultHandle - sequenced_task_runner_current_default_; - }; - - // CurrentHandleOverride overrides the task runner returned by - // |SingleThreadTaskRunner::GetCurrentDefault()| to point at - // |overriding_task_runner| until the |CurrentHandleOverride| goes out of - // scope. CurrentHandleOverride instantiates a new SingleThreadTaskRunner if - // SingleThreadTaskRunner is not instantiated on the current thread. Nested - // overrides are allowed but callers must ensure the |CurrentHandleOverride|s - // expire in LIFO (stack) order. - // - // Note: nesting SingleThreadTaskRunner is subtle and should be done with - // care, hence the need to friend and request a //base/OWNERS review for usage - // outside of tests. Use CurrentHandleOverrideForTesting to bypass the friend - // requirement in tests. - class BASE_EXPORT CurrentHandleOverride { - public: - CurrentHandleOverride(const CurrentHandleOverride&) = delete; - CurrentHandleOverride& operator=(const CurrentHandleOverride&) = delete; - ~CurrentHandleOverride(); - - private: - friend class CurrentHandleOverrideForTesting; - FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, - NestedRunLoop); - - // We expect SingleThreadTaskRunner::CurrentHandleOverride to be only needed - // under special circumstances. Require them to be enumerated as friends to - // require //base/OWNERS review. Use + // Overriding an existing current default SingleThreadTaskRunner should only + // be needed under special circumstances. Require them to be enumerated as + // friends to require //base/OWNERS review. Use // SingleThreadTaskRunner::CurrentHandleOverrideForTesting in unit tests to // avoid the friend requirement. - friend class blink::scheduler::MainThreadSchedulerImpl; + friend class CurrentHandleOverrideForTesting; + friend class sequence_manager::internal:: + CurrentDefaultHandleOverrideForRunOrPostTask; + FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, + NestedRunLoopAllowedUnderHandleOverride); + FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, + NestedOverrideWithMayAlreadyExist); + FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, + OverrideWithNull); + FRIEND_TEST_ALL_PREFIXES(SingleThreadTaskRunnerCurrentDefaultHandleTest, + OverrideWithNonNull); - // Constructs a SingleThreadTaskRunner::CurrentHandleOverride which will - // make SingleThreadTaskRunner::GetCurrentDefault() return - // |overriding_task_runner| for its lifetime. |allow_nested_loop| specifies - // whether RunLoop::Run() is allowed during this override's lifetime. It's - // not recommended to allow this unless the current thread's scheduler - // guarantees that only tasks which pertain to |overriding_task_runner|'s - // context will be run by nested RunLoops. - explicit CurrentHandleOverride( - scoped_refptr overriding_task_runner, - bool allow_nested_runloop = false); + struct MayAlreadyExist {}; - absl::optional - top_level_thread_task_runner_current_default_; + // Same as the public constructor, but there may already be a current + // default `SingleThreadTaskRunner` on this thread. + CurrentDefaultHandle(scoped_refptr task_runner, + MayAlreadyExist); - scoped_refptr task_runner_to_restore_; - -#if DCHECK_IS_ON() - raw_ptr expected_task_runner_before_restore_{ - nullptr}; -#endif - - std::unique_ptr no_running_during_override_; + scoped_refptr task_runner_; + raw_ptr previous_handle_; + SequencedTaskRunner::CurrentDefaultHandle sequenced_handle_; }; - // Note: nesting CurrentHandleOverrides isn't generally desired but it's - // useful in some unit tests where multiple task runners share the main thread - // for simplicity and determinism. Only use this when no other constructs will - // work (see base/test/task_environment.h and + // Overrides the current default `SingleThreadTaskRunner` and disables running + // a `RunLoop` within its scope. + // + // Note: Overriding the current default SingleThreadTaskRunner isn't generally + // desired but it's useful in some unit tests where multiple task runners + // share the main thread for simplicity and determinism. Only use this when no + // other constructs will work (see base/test/task_environment.h and // base/test/test_mock_time_task_runner.h for preferred alternatives). class BASE_EXPORT CurrentHandleOverrideForTesting { public: explicit CurrentHandleOverrideForTesting( - scoped_refptr overriding_task_runner) - : thread_task_runner_current_override_( - std::move(overriding_task_runner)) {} + scoped_refptr overriding_task_runner); + ~CurrentHandleOverrideForTesting(); private: - CurrentHandleOverride thread_task_runner_current_override_; + CurrentDefaultHandle current_default_handle_; + std::unique_ptr no_running_during_override_; }; protected: diff --git a/naiveproxy/src/base/task/task_features.cc b/naiveproxy/src/base/task/task_features.cc index 9d09b23e00..b69c77c130 100644 --- a/naiveproxy/src/base/task/task_features.cc +++ b/naiveproxy/src/base/task/task_features.cc @@ -75,8 +75,10 @@ BASE_FEATURE(kMaxDelayedStarvationTasks, const base::FeatureParam kMaxDelayedStarvationTasksParam{ &kMaxDelayedStarvationTasks, "count", 3}; -BASE_FEATURE(kUseNewJobImplementation, - "UseNewJobImplementation", +BASE_FEATURE(kThreadGroupSemaphore, + "ThreadGroupSemaphore", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam kMaxNumWorkersCreated{ + &kThreadGroupSemaphore, "max_num_workers_created", 2}; } // namespace base diff --git a/naiveproxy/src/base/task/task_features.h b/naiveproxy/src/base/task/task_features.h index 5a1a3c47c8..e8611ac102 100644 --- a/naiveproxy/src/base/task/task_features.h +++ b/naiveproxy/src/base/task/task_features.h @@ -66,8 +66,9 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kMaxDelayedStarvationTasks); extern const BASE_EXPORT base::FeatureParam kMaxDelayedStarvationTasksParam; -// Feature to use a JobTaskSource implementation that minimizes lock contention. -BASE_EXPORT BASE_DECLARE_FEATURE(kUseNewJobImplementation); +// Feature to use ThreadGroupSemaphore instead of ThreadGroupImpl. +BASE_EXPORT BASE_DECLARE_FEATURE(kThreadGroupSemaphore); +extern const BASE_EXPORT base::FeatureParam kMaxNumWorkersCreated; } // namespace base diff --git a/naiveproxy/src/base/task/thread_pool/job_task_source.cc b/naiveproxy/src/base/task/thread_pool/job_task_source.cc index 1b70c2e729..be531a9f2d 100644 --- a/naiveproxy/src/base/task/thread_pool/job_task_source.cc +++ b/naiveproxy/src/base/task/thread_pool/job_task_source.cc @@ -5,20 +5,25 @@ #include "base/task/thread_pool/job_task_source.h" #include -#include #include +#include #include "base/check_op.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/memory/ptr_util.h" #include "base/notreached.h" #include "base/task/common/checked_lock.h" +#include "base/task/task_features.h" #include "base/task/thread_pool/pooled_task_runner_delegate.h" +#include "base/template_util.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" +#include "base/time/time_override.h" #include "base/trace_event/base_tracing.h" -namespace base::internal { +namespace base { +namespace internal { namespace { @@ -33,105 +38,65 @@ static_assert( } // namespace -JobTaskSourceNew::State::State() = default; -JobTaskSourceNew::State::~State() = default; +JobTaskSource::State::State() = default; +JobTaskSource::State::~State() = default; -JobTaskSourceNew::State::Value JobTaskSourceNew::State::Cancel() { +JobTaskSource::State::Value JobTaskSource::State::Cancel() { return {value_.fetch_or(kCanceledMask, std::memory_order_relaxed)}; } -JobTaskSourceNew::State::Value JobTaskSourceNew::State::IncrementWorkerCount() { - uint32_t prev = +JobTaskSource::State::Value JobTaskSource::State::DecrementWorkerCount() { + const uint32_t value_before_sub = + value_.fetch_sub(kWorkerCountIncrement, std::memory_order_relaxed); + DCHECK((value_before_sub >> kWorkerCountBitOffset) > 0); + return {value_before_sub}; +} + +JobTaskSource::State::Value JobTaskSource::State::IncrementWorkerCount() { + uint32_t value_before_add = value_.fetch_add(kWorkerCountIncrement, std::memory_order_relaxed); // The worker count must not overflow a uint8_t. - DCHECK((prev >> kWorkerCountBitOffset) < ((1 << 8) - 1)); - return {prev}; + DCHECK((value_before_add >> kWorkerCountBitOffset) < ((1 << 8) - 1)); + return {value_before_add}; } -JobTaskSourceNew::State::Value JobTaskSourceNew::State::DecrementWorkerCount() { - uint32_t prev = - value_.fetch_sub(kWorkerCountIncrement, std::memory_order_relaxed); - DCHECK((prev >> kWorkerCountBitOffset) > 0); - return {prev}; -} - -JobTaskSourceNew::State::Value JobTaskSourceNew::State::RequestSignalJoin() { - uint32_t prev = value_.fetch_or(kSignalJoinMask, std::memory_order_relaxed); - return {prev}; -} - -bool JobTaskSourceNew::State::FetchAndResetRequestSignalJoin() { - uint32_t prev = value_.fetch_and(~kSignalJoinMask, std::memory_order_relaxed); - return !!(prev & kSignalJoinMask); -} - -bool JobTaskSourceNew::State::ShouldQueueUponCapacityIncrease() { - // If `WillRunTask()` is running: setting - // `kOutsideWillRunTaskOrMustReenqueueMask` ensures that this capacity - // increase is taken into account in the returned `RunStatus`. - // - // If `WillRunTask()` is not running, setting - // `kOutsideWillRunTaskOrMustReenqueueMask` is a no-op (already set). - // - // Release paired with Acquire in `ExitWillRunTask()`, see comment there. - Value prev{ - value_.fetch_or(kQueuedMask | kOutsideWillRunTaskOrMustReenqueueMask, - std::memory_order_release)}; - return !prev.queued() && prev.outside_will_run_task_or_must_reenqueue(); -} - -JobTaskSourceNew::State::Value JobTaskSourceNew::State::EnterWillRunTask() { - Value prev{ - value_.fetch_and(~(kQueuedMask | kOutsideWillRunTaskOrMustReenqueueMask), - std::memory_order_relaxed)}; - CHECK(prev.outside_will_run_task_or_must_reenqueue()); - return {prev}; -} - -bool JobTaskSourceNew::State::ExitWillRunTask(bool saturated) { - uint32_t bits_to_set = kOutsideWillRunTaskOrMustReenqueueMask; - if (!saturated) { - // If the task source is not saturated, it will be re-enqueued. - bits_to_set |= kQueuedMask; - } - - // Acquire paired with Release in `ShouldQueueUponCapacityIncrease()` or - // `WillReenqueue()` so that anything that runs after clearing - // `kOutsideWillRunTaskOrMustReenqueueMask` sees max concurrency changes - // applied before setting it. - Value prev{value_.fetch_or(bits_to_set, std::memory_order_acquire)}; - - // `kQueuedMask` and `kOutsideWillRunTaskOrMustReenqueueMask` were cleared by - // `EnterWillRunTask()`. Since then, they may have *both* been set by - // `ShouldQueueUponCapacityIncrease()` or `WillReenqueue()`. - CHECK_EQ(prev.queued(), prev.outside_will_run_task_or_must_reenqueue()); - - return prev.outside_will_run_task_or_must_reenqueue(); -} - -bool JobTaskSourceNew::State::WillReenqueue() { - // Release paired with Acquire in `ExitWillRunTask()`, see comment there. - Value prev{ - value_.fetch_or(kQueuedMask | kOutsideWillRunTaskOrMustReenqueueMask, - std::memory_order_release)}; - return prev.outside_will_run_task_or_must_reenqueue(); -} - -JobTaskSourceNew::State::Value JobTaskSourceNew::State::Load() const { +JobTaskSource::State::Value JobTaskSource::State::Load() const { return {value_.load(std::memory_order_relaxed)}; } -JobTaskSourceNew::JobTaskSourceNew( - const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate) - : JobTaskSource(traits, TaskSourceExecutionMode::kJob), +JobTaskSource::JoinFlag::JoinFlag() = default; +JobTaskSource::JoinFlag::~JoinFlag() = default; + +void JobTaskSource::JoinFlag::Reset() { + value_.store(kNotWaiting, std::memory_order_relaxed); +} + +void JobTaskSource::JoinFlag::SetWaiting() { + value_.store(kWaitingForWorkerToYield, std::memory_order_relaxed); +} + +bool JobTaskSource::JoinFlag::ShouldWorkerYield() { + // The fetch_and() sets the state to kWaitingForWorkerToSignal if it was + // previously kWaitingForWorkerToYield, otherwise it leaves it unchanged. + return value_.fetch_and(kWaitingForWorkerToSignal, + std::memory_order_relaxed) == + kWaitingForWorkerToYield; +} + +bool JobTaskSource::JoinFlag::ShouldWorkerSignal() { + return value_.exchange(kNotWaiting, std::memory_order_relaxed) != kNotWaiting; +} + +JobTaskSource::JobTaskSource(const Location& from_here, + const TaskTraits& traits, + RepeatingCallback worker_task, + MaxConcurrencyCallback max_concurrency_callback, + PooledTaskRunnerDelegate* delegate) + : TaskSource(traits, TaskSourceExecutionMode::kJob), max_concurrency_callback_(std::move(max_concurrency_callback)), worker_task_(std::move(worker_task)), primary_task_(base::BindRepeating( - [](JobTaskSourceNew* self) { + [](JobTaskSource* self) { CheckedLock::AssertNoLockHeldOnCurrentThread(); // Each worker task has its own delegate with associated state. JobDelegate job_delegate{self, self->delegate_}; @@ -143,21 +108,18 @@ JobTaskSourceNew::JobTaskSourceNew( delegate_(delegate) { DCHECK(delegate_); task_metadata_.sequence_num = -1; - // Prevent wait on `join_event_` from triggering a ScopedBlockingCall as this - // would acquire `ThreadGroup::lock_` and cause lock inversion. - join_event_.declare_only_used_while_idle(); } -JobTaskSourceNew::~JobTaskSourceNew() { +JobTaskSource::~JobTaskSource() { // Make sure there's no outstanding active run operation left. DCHECK_EQ(state_.Load().worker_count(), 0U); } -ExecutionEnvironment JobTaskSourceNew::GetExecutionEnvironment() { +ExecutionEnvironment JobTaskSource::GetExecutionEnvironment() { return {SequenceToken::Create()}; } -void JobTaskSourceNew::WillEnqueue(int sequence_num, TaskAnnotator& annotator) { +void JobTaskSource::WillEnqueue(int sequence_num, TaskAnnotator& annotator) { if (task_metadata_.sequence_num != -1) { // WillEnqueue() was already called. return; @@ -166,17 +128,17 @@ void JobTaskSourceNew::WillEnqueue(int sequence_num, TaskAnnotator& annotator) { annotator.WillQueueTask("ThreadPool_PostJob", &task_metadata_); } -bool JobTaskSourceNew::WillJoin() { - // Increment worker count to indicate that this thread participates. - State::Value state_before_add; - { - CheckedAutoLock auto_lock(state_.increment_worker_count_lock()); - state_before_add = state_.IncrementWorkerCount(); - } +bool JobTaskSource::WillJoin() { + TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity"); + CheckedAutoLock auto_lock(worker_lock_); + DCHECK(!worker_released_condition_); // This may only be called once. + worker_released_condition_ = worker_lock_.CreateConditionVariable(); + // Prevent wait from triggering a ScopedBlockingCall as this would cause + // |ThreadGroup::lock_| to be acquired, causing lock inversion. + worker_released_condition_->declare_only_used_while_idle(); + const auto state_before_add = state_.IncrementWorkerCount(); - // Return when the job is canceled or the (newly incremented) worker count is - // below or equal to max concurrency. - if (!state_before_add.canceled() && + if (!state_before_add.is_canceled() && state_before_add.worker_count() < GetMaxConcurrency(state_before_add.worker_count())) { return true; @@ -184,136 +146,116 @@ bool JobTaskSourceNew::WillJoin() { return WaitForParticipationOpportunity(); } -bool JobTaskSourceNew::RunJoinTask() { - { - TRACE_EVENT0("base", "Job.JoinParticipates"); - JobDelegate job_delegate{this, nullptr}; - worker_task_.Run(&job_delegate); - } +bool JobTaskSource::RunJoinTask() { + JobDelegate job_delegate{this, nullptr}; + worker_task_.Run(&job_delegate); - const auto state = state_.Load(); + // It is safe to read |state_| without a lock since this variable is atomic + // and the call to GetMaxConcurrency() is used for a best effort early exit. + // Stale values will only cause WaitForParticipationOpportunity() to be + // called. + const auto state = TS_UNCHECKED_READ(state_).Load(); // The condition is slightly different from the one in WillJoin() since we're // using |state| that was already incremented to include the joining thread. - if (!state.canceled() && + if (!state.is_canceled() && state.worker_count() <= GetMaxConcurrency(state.worker_count() - 1)) { return true; } + TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity"); + CheckedAutoLock auto_lock(worker_lock_); return WaitForParticipationOpportunity(); } -void JobTaskSourceNew::Cancel(TaskSource::Transaction* transaction) { +void JobTaskSource::Cancel(TaskSource::Transaction* transaction) { // Sets the kCanceledMask bit on |state_| so that further calls to // WillRunTask() never succeed. std::memory_order_relaxed without a lock is // safe because this task source never needs to be re-enqueued after Cancel(). - state_.Cancel(); + TS_UNCHECKED_READ(state_).Cancel(); } -bool JobTaskSourceNew::WaitForParticipationOpportunity() { - TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity"); +// EXCLUSIVE_LOCK_REQUIRED(worker_lock_) +bool JobTaskSource::WaitForParticipationOpportunity() { + DCHECK(!join_flag_.IsWaiting()); + + // std::memory_order_relaxed is sufficient because no other state is + // synchronized with |state_| outside of |lock_|. + auto state = state_.Load(); + // |worker_count - 1| to exclude the joining thread which is not active. + size_t max_concurrency = GetMaxConcurrency(state.worker_count() - 1); // Wait until either: - // A) `worker_count` <= "max concurrency" and state is not canceled. - // B) All other workers returned and `worker_count` is 1. - for (;;) { - auto state = state_.RequestSignalJoin(); + // A) |worker_count| is below or equal to max concurrency and state is not + // canceled. + // B) All other workers returned and |worker_count| is 1. + while (!((state.worker_count() <= max_concurrency && !state.is_canceled()) || + state.worker_count() == 1)) { + // std::memory_order_relaxed is sufficient because no other state is + // synchronized with |join_flag_| outside of |lock_|. + join_flag_.SetWaiting(); - size_t max_concurrency = GetMaxConcurrency(state.worker_count() - 1); - - // Case A: - if (state.worker_count() <= max_concurrency && !state.canceled()) { - state_.FetchAndResetRequestSignalJoin(); - return true; - } - - // Case B: - // Only the joining thread remains. - if (state.worker_count() == 1U) { - DCHECK(state.canceled() || max_concurrency == 0U); - // WillRunTask() can run concurrently with this. Synchronize with it via a - // lock to guarantee that the ordering is one of these 2 options: - // 1. WillRunTask is first. It increments worker count. The condition - // below detects that worker count is no longer 1 and we loop again. - // 2. This runs first. It cancels the job. WillRunTask returns - // RunStatus::kDisallowed and doesn't increment the worker count. - // We definitely don't want this 3rd option (made impossible by the lock): - // 3. WillRunTask() observes that the job is not canceled. This observes - // that the worker count is 1 and returns. JobHandle::Join returns and - // its owner deletes state needed by the worker task. WillRunTask() - // increments the worker count and the worker task stats running --> - // use-after-free. - CheckedAutoLock auto_lock(state_.increment_worker_count_lock()); - - if (state_.Load().worker_count() != 1U) { - continue; - } - - state_.Cancel(); - state_.FetchAndResetRequestSignalJoin(); - state_.DecrementWorkerCount(); - return false; - } - - join_event_.Wait(); + // To avoid unnecessarily waiting, if either condition A) or B) change + // |lock_| is taken and |worker_released_condition_| signaled if necessary: + // 1- In DidProcessTask(), after worker count is decremented. + // 2- In NotifyConcurrencyIncrease(), following a max_concurrency increase. + worker_released_condition_->Wait(); + state = state_.Load(); + // |worker_count - 1| to exclude the joining thread which is not active. + max_concurrency = GetMaxConcurrency(state.worker_count() - 1); } + // It's possible though unlikely that the joining thread got a participation + // opportunity without a worker signaling. + join_flag_.Reset(); + + // Case A: + if (state.worker_count() <= max_concurrency && !state.is_canceled()) { + return true; + } + // Case B: + // Only the joining thread remains. + DCHECK_EQ(state.worker_count(), 1U); + DCHECK(state.is_canceled() || max_concurrency == 0U); + state_.DecrementWorkerCount(); + // Prevent subsequent accesses to user callbacks. + state_.Cancel(); + return false; } -TaskSource::RunStatus JobTaskSourceNew::WillRunTask() { - // The lock below prevents a race described in Case B of - // `WaitForParticipationOpportunity()`. - CheckedAutoLock auto_lock(state_.increment_worker_count_lock()); +TaskSource::RunStatus JobTaskSource::WillRunTask() { + CheckedAutoLock auto_lock(worker_lock_); + auto state_before_add = state_.Load(); - for (;;) { - auto prev_state = state_.EnterWillRunTask(); - - // Don't allow this worker to run the task if either: - // A) Job was cancelled. - // B) `worker_count` is already at `max_concurrency`. - // C) `max_concurrency` was lowered below or to `worker_count`. - - // Case A: - if (prev_state.canceled()) { - state_.ExitWillRunTask(/* saturated=*/true); - return RunStatus::kDisallowed; - } - - const size_t worker_count_before_increment = prev_state.worker_count(); - const size_t max_concurrency = - GetMaxConcurrency(worker_count_before_increment); - - if (worker_count_before_increment < max_concurrency) { - prev_state = state_.IncrementWorkerCount(); - // Worker count may have been decremented since it was read, but not - // incremented, due to the lock. - CHECK_LE(prev_state.worker_count(), worker_count_before_increment); - bool saturated = max_concurrency == (worker_count_before_increment + 1); - bool concurrency_increased_during_will_run_task = - state_.ExitWillRunTask(saturated); - - if (saturated && !concurrency_increased_during_will_run_task) { - return RunStatus::kAllowedSaturated; - } - - return RunStatus::kAllowedNotSaturated; - } - - // Case B or C: - bool concurrency_increased_during_will_run_task = - state_.ExitWillRunTask(/* saturated=*/true); - if (!concurrency_increased_during_will_run_task) { - return RunStatus::kDisallowed; - } - - // If concurrency increased during `WillRunTask()`, loop again to - // re-evaluate the `RunStatus`. + // Don't allow this worker to run the task if either: + // A) |state_| was canceled. + // B) |worker_count| is already at |max_concurrency|. + // C) |max_concurrency| was lowered below or to |worker_count|. + // Case A: + if (state_before_add.is_canceled()) { + return RunStatus::kDisallowed; } + + const size_t max_concurrency = + GetMaxConcurrency(state_before_add.worker_count()); + if (state_before_add.worker_count() < max_concurrency) { + state_before_add = state_.IncrementWorkerCount(); + } + const size_t worker_count_before_add = state_before_add.worker_count(); + // Case B) or C): + if (worker_count_before_add >= max_concurrency) { + return RunStatus::kDisallowed; + } + + DCHECK_LT(worker_count_before_add, max_concurrency); + return max_concurrency == worker_count_before_add + 1 + ? RunStatus::kAllowedSaturated + : RunStatus::kAllowedNotSaturated; } -size_t JobTaskSourceNew::GetRemainingConcurrency() const { +size_t JobTaskSource::GetRemainingConcurrency() const { // It is safe to read |state_| without a lock since this variable is atomic, // and no other state is synchronized with GetRemainingConcurrency(). - const auto state = state_.Load(); - if (state.canceled()) { + const auto state = TS_UNCHECKED_READ(state_).Load(); + if (state.is_canceled()) { return 0; } const size_t max_concurrency = GetMaxConcurrency(state.worker_count()); @@ -323,54 +265,52 @@ size_t JobTaskSourceNew::GetRemainingConcurrency() const { return max_concurrency - state.worker_count(); } -bool JobTaskSourceNew::IsActive() const { +bool JobTaskSource::IsActive() const { + CheckedAutoLock auto_lock(worker_lock_); auto state = state_.Load(); return GetMaxConcurrency(state.worker_count()) != 0 || state.worker_count() != 0; } -size_t JobTaskSourceNew::GetWorkerCount() const { - return state_.Load().worker_count(); +size_t JobTaskSource::GetWorkerCount() const { + return TS_UNCHECKED_READ(state_).Load().worker_count(); } -bool JobTaskSourceNew::NotifyConcurrencyIncrease() { - const auto state = state_.Load(); - - // No need to signal the joining thread of re-enqueue if canceled. - if (state.canceled()) { - return true; +void JobTaskSource::NotifyConcurrencyIncrease() { + // Avoid unnecessary locks when NotifyConcurrencyIncrease() is spuriously + // called. + if (GetRemainingConcurrency() == 0) { + return; } - const auto worker_count = state.worker_count(); - const auto max_concurrency = GetMaxConcurrency(worker_count); - - // Signal the joining thread if there is a request to do so and there is room - // for the joining thread to participate. - if (worker_count <= max_concurrency && - state_.FetchAndResetRequestSignalJoin()) { - join_event_.Signal(); + { + // Lock is taken to access |join_flag_| below and signal + // |worker_released_condition_|. + CheckedAutoLock auto_lock(worker_lock_); + if (join_flag_.ShouldWorkerSignal()) { + worker_released_condition_->Signal(); + } } - // The job should be queued if the max concurrency isn't reached and it's not - // already queued. - if (worker_count < max_concurrency && - state_.ShouldQueueUponCapacityIncrease()) { - return delegate_->EnqueueJobTaskSource(this); - } - - return true; + // Make sure the task source is in the queue if not already. + // Caveat: it's possible but unlikely that the task source has already reached + // its intended concurrency and doesn't need to be enqueued if there + // previously were too many worker. For simplicity, the task source is always + // enqueued and will get discarded if already saturated when it is popped from + // the priority queue. + delegate_->EnqueueJobTaskSource(this); } -size_t JobTaskSourceNew::GetMaxConcurrency() const { - return GetMaxConcurrency(state_.Load().worker_count()); +size_t JobTaskSource::GetMaxConcurrency() const { + return GetMaxConcurrency(TS_UNCHECKED_READ(state_).Load().worker_count()); } -size_t JobTaskSourceNew::GetMaxConcurrency(size_t worker_count) const { +size_t JobTaskSource::GetMaxConcurrency(size_t worker_count) const { return std::min(max_concurrency_callback_.Run(worker_count), kMaxWorkersPerJob); } -uint8_t JobTaskSourceNew::AcquireTaskId() { +uint8_t JobTaskSource::AcquireTaskId() { static_assert(kMaxWorkersPerJob <= sizeof(assigned_task_ids_) * 8, "TaskId bitfield isn't big enough to fit kMaxWorkersPerJob."); uint32_t assigned_task_ids = @@ -391,91 +331,83 @@ uint8_t JobTaskSourceNew::AcquireTaskId() { return static_cast(task_id); } -void JobTaskSourceNew::ReleaseTaskId(uint8_t task_id) { +void JobTaskSource::ReleaseTaskId(uint8_t task_id) { // memory_order_release to match AcquireTaskId(). uint32_t previous_task_ids = assigned_task_ids_.fetch_and( ~(uint32_t(1) << task_id), std::memory_order_release); DCHECK(previous_task_ids & (uint32_t(1) << task_id)); } -bool JobTaskSourceNew::ShouldYield() { - // It's safe to read `state_` without a lock because it's atomic, keeping in - // mind that threads may not immediately see the new value when it's updated. - return state_.Load().canceled(); +bool JobTaskSource::ShouldYield() { + // It is safe to read |join_flag_| and |state_| without a lock since these + // variables are atomic, keeping in mind that threads may not immediately see + // the new value when it is updated. + return TS_UNCHECKED_READ(join_flag_).ShouldWorkerYield() || + TS_UNCHECKED_READ(state_).Load().is_canceled(); } -PooledTaskRunnerDelegate* JobTaskSourceNew::GetDelegate() const { - return delegate_; -} - -Task JobTaskSourceNew::TakeTask(TaskSource::Transaction* transaction) { +Task JobTaskSource::TakeTask(TaskSource::Transaction* transaction) { // JobTaskSource members are not lock-protected so no need to acquire a lock // if |transaction| is nullptr. - DCHECK_GT(state_.Load().worker_count(), 0U); + DCHECK_GT(TS_UNCHECKED_READ(state_).Load().worker_count(), 0U); DCHECK(primary_task_); return {task_metadata_, primary_task_}; } -bool JobTaskSourceNew::DidProcessTask( - TaskSource::Transaction* /*transaction*/) { - auto state = state_.Load(); - size_t worker_count_excluding_this = state.worker_count() - 1; +bool JobTaskSource::DidProcessTask(TaskSource::Transaction* /*transaction*/) { + // Lock is needed to access |join_flag_| below and signal + // |worker_released_condition_|. + CheckedAutoLock auto_lock(worker_lock_); + const auto state_before_sub = state_.DecrementWorkerCount(); - // Invoke the max concurrency callback before decrementing the worker count, - // because as soon as the worker count is decremented, JobHandle::Join() can - // return and state needed the callback may be deleted. Also, as an - // optimization, avoid invoking the callback if the job is canceled. - size_t max_concurrency = - state.canceled() ? 0U : GetMaxConcurrency(worker_count_excluding_this); - - state = state_.DecrementWorkerCount(); - if (state.signal_join() && state_.FetchAndResetRequestSignalJoin()) { - join_event_.Signal(); + if (join_flag_.ShouldWorkerSignal()) { + worker_released_condition_->Signal(); } - // A canceled task source should not be re-enqueued. - if (state.canceled()) { + // A canceled task source should never get re-enqueued. + if (state_before_sub.is_canceled()) { return false; } - // Re-enqueue if there isn't enough concurrency. - if (worker_count_excluding_this < max_concurrency) { - return state_.WillReenqueue(); - } + DCHECK_GT(state_before_sub.worker_count(), 0U); - return false; + // Re-enqueue the TaskSource if the task ran and the worker count is below the + // max concurrency. + // |worker_count - 1| to exclude the returning thread. + return state_before_sub.worker_count() <= + GetMaxConcurrency(state_before_sub.worker_count() - 1); } // This is a no-op and should always return true. -bool JobTaskSourceNew::WillReEnqueue(TimeTicks now, - TaskSource::Transaction* /*transaction*/) { +bool JobTaskSource::WillReEnqueue(TimeTicks now, + TaskSource::Transaction* /*transaction*/) { return true; } // This is a no-op. -bool JobTaskSourceNew::OnBecomeReady() { +bool JobTaskSource::OnBecomeReady() { return false; } -TaskSourceSortKey JobTaskSourceNew::GetSortKey() const { +TaskSourceSortKey JobTaskSource::GetSortKey() const { return TaskSourceSortKey(priority_racy(), ready_time_, - state_.Load().worker_count()); + TS_UNCHECKED_READ(state_).Load().worker_count()); } // This function isn't expected to be called since a job is never delayed. // However, the class still needs to provide an override. -TimeTicks JobTaskSourceNew::GetDelayedSortKey() const { +TimeTicks JobTaskSource::GetDelayedSortKey() const { return TimeTicks(); } // This function isn't expected to be called since a job is never delayed. // However, the class still needs to provide an override. -bool JobTaskSourceNew::HasReadyTasks(TimeTicks now) const { +bool JobTaskSource::HasReadyTasks(TimeTicks now) const { NOTREACHED(); return true; } -absl::optional JobTaskSourceNew::Clear( +absl::optional JobTaskSource::Clear( TaskSource::Transaction* transaction) { Cancel(); @@ -485,4 +417,5 @@ absl::optional JobTaskSourceNew::Clear( return absl::nullopt; } -} // namespace base::internal +} // namespace internal +} // namespace base diff --git a/naiveproxy/src/base/task/thread_pool/job_task_source.h b/naiveproxy/src/base/task/thread_pool/job_task_source.h index cd7c973ca6..107052c39e 100644 --- a/naiveproxy/src/base/task/thread_pool/job_task_source.h +++ b/naiveproxy/src/base/task/thread_pool/job_task_source.h @@ -8,63 +8,69 @@ #include #include -#include +#include +#include #include #include "base/base_export.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" -#include "base/synchronization/waitable_event.h" +#include "base/synchronization/condition_variable.h" #include "base/task/common/checked_lock.h" #include "base/task/common/task_annotator.h" #include "base/task/post_job.h" #include "base/task/task_traits.h" -#include "base/task/thread_pool/job_task_source_interface.h" #include "base/task/thread_pool/task.h" #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/task_source_sort_key.h" -namespace base::internal { +namespace base { +namespace internal { class PooledTaskRunnerDelegate; // A JobTaskSource generates many Tasks from a single RepeatingClosure. // // Derived classes control the intended concurrency with GetMaxConcurrency(). -class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { +class BASE_EXPORT JobTaskSource : public TaskSource { public: - JobTaskSourceNew(const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate); - JobTaskSourceNew(const JobTaskSource&) = delete; - JobTaskSourceNew& operator=(const JobTaskSourceNew&) = delete; + JobTaskSource(const Location& from_here, + const TaskTraits& traits, + RepeatingCallback worker_task, + MaxConcurrencyCallback max_concurrency_callback, + PooledTaskRunnerDelegate* delegate); + JobTaskSource(const JobTaskSource&) = delete; + JobTaskSource& operator=(const JobTaskSource&) = delete; + + static JobHandle CreateJobHandle( + scoped_refptr task_source) { + return JobHandle(std::move(task_source)); + } // Called before the task source is enqueued to initialize task metadata. - void WillEnqueue(int sequence_num, TaskAnnotator& annotator) override; + void WillEnqueue(int sequence_num, TaskAnnotator& annotator); - // Notifies this task source that max concurrency increased. Returns false iff - // there was an unsuccessful attempt to enqueue the task source. - bool NotifyConcurrencyIncrease() override; + // Notifies this task source that max concurrency was increased, and the + // number of worker should be adjusted. + void NotifyConcurrencyIncrease(); // Informs this JobTaskSource that the current thread would like to join and // contribute to running |worker_task|. Returns true if the joining thread can // contribute (RunJoinTask() can be called), or false if joining was completed // and all other workers returned because either there's no work remaining or // Job was cancelled. - bool WillJoin() override; + bool WillJoin(); // Contributes to running |worker_task| and returns true if the joining thread // can contribute again (RunJoinTask() can be called again), or false if // joining was completed and all other workers returned because either there's // no work remaining or Job was cancelled. This should be called only after // WillJoin() or RunJoinTask() previously returned true. - bool RunJoinTask() override; + bool RunJoinTask(); // Cancels this JobTaskSource, causing all workers to yield and WillRunTask() // to return RunStatus::kDisallowed. - void Cancel(TaskSource::Transaction* transaction = nullptr) override; + void Cancel(TaskSource::Transaction* transaction = nullptr); // TaskSource: ExecutionEnvironment GetExecutionEnvironment() override; @@ -73,40 +79,31 @@ class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { TimeTicks GetDelayedSortKey() const override; bool HasReadyTasks(TimeTicks now) const override; - bool IsActive() const override; - size_t GetWorkerCount() const override; + bool IsActive() const; + size_t GetWorkerCount() const; // Returns the maximum number of tasks from this TaskSource that can run // concurrently. - size_t GetMaxConcurrency() const override; + size_t GetMaxConcurrency() const; - uint8_t AcquireTaskId() override; - void ReleaseTaskId(uint8_t task_id) override; + uint8_t AcquireTaskId(); + void ReleaseTaskId(uint8_t task_id); // Returns true if a worker should return from the worker task on the current // thread ASAP. - bool ShouldYield() override; + bool ShouldYield(); - PooledTaskRunnerDelegate* GetDelegate() const override; + PooledTaskRunnerDelegate* delegate() const { return delegate_; } private: - // Atomic variable to track job state. + // Atomic internal state to track the number of workers running a task from + // this JobTaskSource and whether this JobTaskSource is canceled. All + // operations are performed with std::memory_order_relaxed as State is only + // ever modified under a lock or read atomically (optimistic read). class State { public: - // When set, the job is canceled. - static constexpr uint32_t kCanceledMask = 1 << 0; - // When set, the Join()'ing thread wants to be signaled when worker count - // is decremented or capacity is created by a max concurrency increase. - static constexpr uint32_t kSignalJoinMask = 1 << 1; - // When set, the job is queued. Note: The job may be queued when this is not - // set, see details in JobTaskSource::State::ExitWillRunTask(). - static constexpr uint32_t kQueuedMask = 1 << 2; - // When set, WillRunTask() is not running *or* WillRunTask() is running and - // there was a request to keep the job queued (via - // `ShouldQueueUponCapacityIncrease()` or `WillReenqueue()`). - static constexpr uint32_t kOutsideWillRunTaskOrMustReenqueueMask = 1 << 3; - // Offset for the number of workers running the job. - static constexpr int kWorkerCountBitOffset = 4; + static constexpr uint32_t kCanceledMask = 1; + static constexpr int kWorkerCountBitOffset = 1; static constexpr uint32_t kWorkerCountIncrement = 1 << kWorkerCountBitOffset; @@ -114,12 +111,8 @@ class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { uint8_t worker_count() const { return static_cast(value >> kWorkerCountBitOffset); } - bool canceled() const { return value & kCanceledMask; } - bool signal_join() const { return value & kSignalJoinMask; } - bool queued() const { return value & kQueuedMask; } - bool outside_will_run_task_or_must_reenqueue() const { - return value & kOutsideWillRunTaskOrMustReenqueueMask; - } + // Returns true if canceled. + bool is_canceled() const { return value & kCanceledMask; } uint32_t value; }; @@ -127,71 +120,76 @@ class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { State(); ~State(); - // Sets as canceled. Returns the state before the operation. + // Sets as canceled. Returns the state + // before the operation. Value Cancel(); // Increments the worker count by 1. Returns the state before the operation. - // - // This requires holding `increment_worker_count_lock()`, to allow - // WaitForParticipationOpportunity() to check worker count and apply changes - // with a guarantee that it hasn't been incremented in between (worker count - // could still be decremented while the lock is held). - Value IncrementWorkerCount() - EXCLUSIVE_LOCKS_REQUIRED(increment_worker_count_lock()); + Value IncrementWorkerCount(); // Decrements the worker count by 1. Returns the state before the operation. Value DecrementWorkerCount(); - // Requests to signal the Join()'ing thread when worker count is - // decremented or capacity is created by increasing "max concurrency". - // Returns the state before the operation. - Value RequestSignalJoin(); - - // Returns whether the Join()'ing thread should be signaled when worker - // count is decremented or capacity is created by increasing "max - // concurrency". Resets the bit so that this won't return true until - // `RequestSignalJoin()` is called again. - bool FetchAndResetRequestSignalJoin(); - - // Indicates that max capacity was increased above the number of workers. - // Returns true iff the job should be queued. - bool ShouldQueueUponCapacityIncrease(); - - // Indicates that WillRunTask() was entered. Returns the previous state. - Value EnterWillRunTask(); - - // Indicates that WillRunTask() will exit. `saturated` is true iff - // `WillRunTask()` determined that max concurrency is reached. Returns true - // iff `ShouldQueueUponCapacityIncrease()` or `WillQueue()` was invoked - // since `EnterWillRunTask()`. - bool ExitWillRunTask(bool saturated); - - // Indicates that `DidProcessTask()` decided to re-enqueue the job. If this - // returns false, the job shouldn't re-enqueue the job (another worker - // currently in `WillRunTask()` will request that it remains in the queue). - bool WillReenqueue(); - // Loads and returns the state. Value Load() const; - // Returns a lock that must be held to call `IncrementWorkerCount()`. - CheckedLock& increment_worker_count_lock() { - return increment_worker_count_lock_; - } - private: - std::atomic value_{kOutsideWillRunTaskOrMustReenqueueMask}; - CheckedLock increment_worker_count_lock_{UniversalSuccessor()}; + std::atomic value_{0}; }; - ~JobTaskSourceNew() override; + // Atomic flag that indicates if the joining thread is currently waiting on + // another worker to yield or to signal. + class JoinFlag { + public: + static constexpr uint32_t kNotWaiting = 0; + static constexpr uint32_t kWaitingForWorkerToSignal = 1; + static constexpr uint32_t kWaitingForWorkerToYield = 3; + // kWaitingForWorkerToYield is 3 because the impl relies on the following + // property. + static_assert((kWaitingForWorkerToYield & kWaitingForWorkerToSignal) == + kWaitingForWorkerToSignal, + ""); + + JoinFlag(); + ~JoinFlag(); + + // Returns true if the status is not kNotWaiting, using + // std::memory_order_relaxed. + bool IsWaiting() { + return value_.load(std::memory_order_relaxed) != kNotWaiting; + } + + // Resets the status as kNotWaiting using std::memory_order_relaxed. + void Reset(); + + // Sets the status as kWaitingForWorkerToYield using + // std::memory_order_relaxed. + void SetWaiting(); + + // If the flag is kWaitingForWorkerToYield, returns true indicating that the + // worker should yield, and atomically updates to kWaitingForWorkerToSignal + // (using std::memory_order_relaxed) to ensure that a single worker yields + // in response to SetWaiting(). + bool ShouldWorkerYield(); + + // If the flag is kWaiting*, returns true indicating that the worker should + // signal, and atomically updates to kNotWaiting (using + // std::memory_order_relaxed) to ensure that a single worker signals in + // response to SetWaiting(). + bool ShouldWorkerSignal(); + + private: + std::atomic value_{kNotWaiting}; + }; + + ~JobTaskSource() override; // Called from the joining thread. Waits for the worker count to be below or - // equal to max concurrency (may happen when "max concurrency" increases or - // the worker count is decremented). Returns true if the joining thread should - // run a task, or false if joining was completed and all other workers - // returned because either there's no work remaining or Job was cancelled. - bool WaitForParticipationOpportunity(); + // equal to max concurrency (will happen when a worker calls + // DidProcessTask()). Returns true if the joining thread should run a task, or + // false if joining was completed and all other workers returned because + // either there's no work remaining or Job was cancelled. + bool WaitForParticipationOpportunity() EXCLUSIVE_LOCKS_REQUIRED(worker_lock_); size_t GetMaxConcurrency(size_t worker_count) const; @@ -204,11 +202,18 @@ class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { TaskSource::Transaction* transaction) override; bool OnBecomeReady() override; - State state_; + // Synchronizes access to workers state. + mutable CheckedLock worker_lock_{UniversalSuccessor()}; - // Signaled when the joining thread wants to particpate and capacity is - // created by increasing "max concurrency" or decrementing the worker count. - WaitableEvent join_event_{WaitableEvent::ResetPolicy::AUTOMATIC}; + // Current atomic state (atomic despite the lock to allow optimistic reads + // and cancellation without the lock). + State state_ GUARDED_BY(worker_lock_); + // Normally, |join_flag_| is protected by |lock_|, except in ShouldYield() + // hence the use of atomics. + JoinFlag join_flag_ GUARDED_BY(worker_lock_); + // Signaled when |join_flag_| is kWaiting* and a worker returns. + std::unique_ptr worker_released_condition_ + GUARDED_BY(worker_lock_); std::atomic assigned_task_ids_{0}; @@ -225,6 +230,7 @@ class BASE_EXPORT JobTaskSourceNew : public JobTaskSource { raw_ptr delegate_; }; -} // namespace base::internal +} // namespace internal +} // namespace base #endif // BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_H_ diff --git a/naiveproxy/src/base/task/thread_pool/job_task_source_interface.h b/naiveproxy/src/base/task/thread_pool/job_task_source_interface.h deleted file mode 100644 index db65228725..0000000000 --- a/naiveproxy/src/base/task/thread_pool/job_task_source_interface.h +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_INTERFACE_H_ -#define BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_INTERFACE_H_ - -#include "base/task/post_job.h" -#include "base/task/thread_pool/task_source.h" - -namespace base { - -class TaskAnnotator; - -namespace internal { - -class PooledTaskRunnerDelegate; - -// Interface for a job task source, to facilitate using either JobTaskSourceNew -// or JobTaskSourceOld depending on the UseNewJobImplementation feature state. -class BASE_EXPORT JobTaskSource : public TaskSource { - public: - JobTaskSource(const JobTaskSource&) = delete; - JobTaskSource& operator=(const JobTaskSource&) = delete; - - static JobHandle CreateJobHandle( - scoped_refptr task_source) { - return JobHandle(std::move(task_source)); - } - - virtual void WillEnqueue(int sequence_num, TaskAnnotator& annotator) = 0; - virtual bool NotifyConcurrencyIncrease() = 0; - virtual bool WillJoin() = 0; - virtual bool RunJoinTask() = 0; - virtual void Cancel(TaskSource::Transaction* transaction = nullptr) = 0; - virtual bool IsActive() const = 0; - virtual size_t GetWorkerCount() const = 0; - virtual size_t GetMaxConcurrency() const = 0; - virtual uint8_t AcquireTaskId() = 0; - virtual void ReleaseTaskId(uint8_t task_id) = 0; - virtual bool ShouldYield() = 0; - virtual PooledTaskRunnerDelegate* GetDelegate() const = 0; - - protected: - JobTaskSource(const TaskTraits& traits, - TaskSourceExecutionMode execution_mode) - : TaskSource(traits, execution_mode) {} - ~JobTaskSource() override = default; -}; - -} // namespace internal -} // namespace base - -#endif // BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_INTERFACE_H_ diff --git a/naiveproxy/src/base/task/thread_pool/job_task_source_old.cc b/naiveproxy/src/base/task/thread_pool/job_task_source_old.cc deleted file mode 100644 index 5fb4856bd3..0000000000 --- a/naiveproxy/src/base/task/thread_pool/job_task_source_old.cc +++ /dev/null @@ -1,427 +0,0 @@ -// 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/task/thread_pool/job_task_source_old.h" - -#include -#include -#include - -#include "base/check_op.h" -#include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" -#include "base/memory/ptr_util.h" -#include "base/notreached.h" -#include "base/task/common/checked_lock.h" -#include "base/task/task_features.h" -#include "base/task/thread_pool/pooled_task_runner_delegate.h" -#include "base/template_util.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "base/time/time_override.h" -#include "base/trace_event/base_tracing.h" - -namespace base { -namespace internal { - -namespace { - -// Capped to allow assigning task_ids from a bitfield. -constexpr size_t kMaxWorkersPerJob = 32; -static_assert( - kMaxWorkersPerJob <= - std::numeric_limits< - std::invoke_result::type>::max(), - "AcquireTaskId return type isn't big enough to fit kMaxWorkersPerJob"); - -} // namespace - -JobTaskSourceOld::State::State() = default; -JobTaskSourceOld::State::~State() = default; - -JobTaskSourceOld::State::Value JobTaskSourceOld::State::Cancel() { - return {value_.fetch_or(kCanceledMask, std::memory_order_relaxed)}; -} - -JobTaskSourceOld::State::Value JobTaskSourceOld::State::DecrementWorkerCount() { - const uint32_t value_before_sub = - value_.fetch_sub(kWorkerCountIncrement, std::memory_order_relaxed); - DCHECK((value_before_sub >> kWorkerCountBitOffset) > 0); - return {value_before_sub}; -} - -JobTaskSourceOld::State::Value JobTaskSourceOld::State::IncrementWorkerCount() { - uint32_t value_before_add = - value_.fetch_add(kWorkerCountIncrement, std::memory_order_relaxed); - // The worker count must not overflow a uint8_t. - DCHECK((value_before_add >> kWorkerCountBitOffset) < ((1 << 8) - 1)); - return {value_before_add}; -} - -JobTaskSourceOld::State::Value JobTaskSourceOld::State::Load() const { - return {value_.load(std::memory_order_relaxed)}; -} - -JobTaskSourceOld::JoinFlag::JoinFlag() = default; -JobTaskSourceOld::JoinFlag::~JoinFlag() = default; - -void JobTaskSourceOld::JoinFlag::Reset() { - value_.store(kNotWaiting, std::memory_order_relaxed); -} - -void JobTaskSourceOld::JoinFlag::SetWaiting() { - value_.store(kWaitingForWorkerToYield, std::memory_order_relaxed); -} - -bool JobTaskSourceOld::JoinFlag::ShouldWorkerYield() { - // The fetch_and() sets the state to kWaitingForWorkerToSignal if it was - // previously kWaitingForWorkerToYield, otherwise it leaves it unchanged. - return value_.fetch_and(kWaitingForWorkerToSignal, - std::memory_order_relaxed) == - kWaitingForWorkerToYield; -} - -bool JobTaskSourceOld::JoinFlag::ShouldWorkerSignal() { - return value_.exchange(kNotWaiting, std::memory_order_relaxed) != kNotWaiting; -} - -JobTaskSourceOld::JobTaskSourceOld( - const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate) - : JobTaskSource(traits, TaskSourceExecutionMode::kJob), - max_concurrency_callback_(std::move(max_concurrency_callback)), - worker_task_(std::move(worker_task)), - primary_task_(base::BindRepeating( - [](JobTaskSourceOld* self) { - CheckedLock::AssertNoLockHeldOnCurrentThread(); - // Each worker task has its own delegate with associated state. - JobDelegate job_delegate{self, self->delegate_}; - self->worker_task_.Run(&job_delegate); - }, - base::Unretained(this))), - task_metadata_(from_here), - ready_time_(TimeTicks::Now()), - delegate_(delegate) { - DCHECK(delegate_); -} - -JobTaskSourceOld::~JobTaskSourceOld() { - // Make sure there's no outstanding active run operation left. - DCHECK_EQ(state_.Load().worker_count(), 0U); -} - -ExecutionEnvironment JobTaskSourceOld::GetExecutionEnvironment() { - return {SequenceToken::Create()}; -} - -void JobTaskSourceOld::WillEnqueue(int sequence_num, TaskAnnotator& annotator) { - if (task_metadata_.sequence_num != -1) { - // WillEnqueue() was already called. - return; - } - task_metadata_.sequence_num = sequence_num; - annotator.WillQueueTask("ThreadPool_PostJob", &task_metadata_); -} - -bool JobTaskSourceOld::WillJoin() { - TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity"); - CheckedAutoLock auto_lock(worker_lock_); - DCHECK(!worker_released_condition_); // This may only be called once. - worker_released_condition_ = worker_lock_.CreateConditionVariable(); - // Prevent wait from triggering a ScopedBlockingCall as this would cause - // |ThreadGroup::lock_| to be acquired, causing lock inversion. - worker_released_condition_->declare_only_used_while_idle(); - const auto state_before_add = state_.IncrementWorkerCount(); - - if (!state_before_add.is_canceled() && - state_before_add.worker_count() < - GetMaxConcurrency(state_before_add.worker_count())) { - return true; - } - return WaitForParticipationOpportunity(); -} - -bool JobTaskSourceOld::RunJoinTask() { - JobDelegate job_delegate{this, nullptr}; - worker_task_.Run(&job_delegate); - - // It is safe to read |state_| without a lock since this variable is atomic - // and the call to GetMaxConcurrency() is used for a best effort early exit. - // Stale values will only cause WaitForParticipationOpportunity() to be - // called. - const auto state = TS_UNCHECKED_READ(state_).Load(); - // The condition is slightly different from the one in WillJoin() since we're - // using |state| that was already incremented to include the joining thread. - if (!state.is_canceled() && - state.worker_count() <= GetMaxConcurrency(state.worker_count() - 1)) { - return true; - } - - TRACE_EVENT0("base", "Job.WaitForParticipationOpportunity"); - CheckedAutoLock auto_lock(worker_lock_); - return WaitForParticipationOpportunity(); -} - -void JobTaskSourceOld::Cancel(TaskSource::Transaction* transaction) { - // Sets the kCanceledMask bit on |state_| so that further calls to - // WillRunTask() never succeed. std::memory_order_relaxed without a lock is - // safe because this task source never needs to be re-enqueued after Cancel(). - TS_UNCHECKED_READ(state_).Cancel(); -} - -// EXCLUSIVE_LOCK_REQUIRED(worker_lock_) -bool JobTaskSourceOld::WaitForParticipationOpportunity() { - DCHECK(!join_flag_.IsWaiting()); - - // std::memory_order_relaxed is sufficient because no other state is - // synchronized with |state_| outside of |lock_|. - auto state = state_.Load(); - // |worker_count - 1| to exclude the joining thread which is not active. - size_t max_concurrency = GetMaxConcurrency(state.worker_count() - 1); - - // Wait until either: - // A) |worker_count| is below or equal to max concurrency and state is not - // canceled. - // B) All other workers returned and |worker_count| is 1. - while (!((state.worker_count() <= max_concurrency && !state.is_canceled()) || - state.worker_count() == 1)) { - // std::memory_order_relaxed is sufficient because no other state is - // synchronized with |join_flag_| outside of |lock_|. - join_flag_.SetWaiting(); - - // To avoid unnecessarily waiting, if either condition A) or B) change - // |lock_| is taken and |worker_released_condition_| signaled if necessary: - // 1- In DidProcessTask(), after worker count is decremented. - // 2- In NotifyConcurrencyIncrease(), following a max_concurrency increase. - worker_released_condition_->Wait(); - state = state_.Load(); - // |worker_count - 1| to exclude the joining thread which is not active. - max_concurrency = GetMaxConcurrency(state.worker_count() - 1); - } - // It's possible though unlikely that the joining thread got a participation - // opportunity without a worker signaling. - join_flag_.Reset(); - - // Case A: - if (state.worker_count() <= max_concurrency && !state.is_canceled()) { - return true; - } - // Case B: - // Only the joining thread remains. - DCHECK_EQ(state.worker_count(), 1U); - DCHECK(state.is_canceled() || max_concurrency == 0U); - state_.DecrementWorkerCount(); - // Prevent subsequent accesses to user callbacks. - state_.Cancel(); - return false; -} - -TaskSource::RunStatus JobTaskSourceOld::WillRunTask() { - CheckedAutoLock auto_lock(worker_lock_); - auto state_before_add = state_.Load(); - - // Don't allow this worker to run the task if either: - // A) |state_| was canceled. - // B) |worker_count| is already at |max_concurrency|. - // C) |max_concurrency| was lowered below or to |worker_count|. - // Case A: - if (state_before_add.is_canceled()) { - return RunStatus::kDisallowed; - } - - const size_t max_concurrency = - GetMaxConcurrency(state_before_add.worker_count()); - if (state_before_add.worker_count() < max_concurrency) { - state_before_add = state_.IncrementWorkerCount(); - } - const size_t worker_count_before_add = state_before_add.worker_count(); - // Case B) or C): - if (worker_count_before_add >= max_concurrency) { - return RunStatus::kDisallowed; - } - - DCHECK_LT(worker_count_before_add, max_concurrency); - return max_concurrency == worker_count_before_add + 1 - ? RunStatus::kAllowedSaturated - : RunStatus::kAllowedNotSaturated; -} - -size_t JobTaskSourceOld::GetRemainingConcurrency() const { - // It is safe to read |state_| without a lock since this variable is atomic, - // and no other state is synchronized with GetRemainingConcurrency(). - const auto state = TS_UNCHECKED_READ(state_).Load(); - if (state.is_canceled()) { - return 0; - } - const size_t max_concurrency = GetMaxConcurrency(state.worker_count()); - // Avoid underflows. - if (state.worker_count() > max_concurrency) { - return 0; - } - return max_concurrency - state.worker_count(); -} - -bool JobTaskSourceOld::IsActive() const { - CheckedAutoLock auto_lock(worker_lock_); - auto state = state_.Load(); - return GetMaxConcurrency(state.worker_count()) != 0 || - state.worker_count() != 0; -} - -size_t JobTaskSourceOld::GetWorkerCount() const { - return TS_UNCHECKED_READ(state_).Load().worker_count(); -} - -bool JobTaskSourceOld::NotifyConcurrencyIncrease() { - // Avoid unnecessary locks when NotifyConcurrencyIncrease() is spuriously - // called. - if (GetRemainingConcurrency() == 0) { - return true; - } - - { - // Lock is taken to access |join_flag_| below and signal - // |worker_released_condition_|. - CheckedAutoLock auto_lock(worker_lock_); - if (join_flag_.ShouldWorkerSignal()) { - worker_released_condition_->Signal(); - } - } - - // Make sure the task source is in the queue if not already. - // Caveat: it's possible but unlikely that the task source has already reached - // its intended concurrency and doesn't need to be enqueued if there - // previously were too many worker. For simplicity, the task source is always - // enqueued and will get discarded if already saturated when it is popped from - // the priority queue. - return delegate_->EnqueueJobTaskSource(this); -} - -size_t JobTaskSourceOld::GetMaxConcurrency() const { - return GetMaxConcurrency(TS_UNCHECKED_READ(state_).Load().worker_count()); -} - -size_t JobTaskSourceOld::GetMaxConcurrency(size_t worker_count) const { - return std::min(max_concurrency_callback_.Run(worker_count), - kMaxWorkersPerJob); -} - -uint8_t JobTaskSourceOld::AcquireTaskId() { - static_assert(kMaxWorkersPerJob <= sizeof(assigned_task_ids_) * 8, - "TaskId bitfield isn't big enough to fit kMaxWorkersPerJob."); - uint32_t assigned_task_ids = - assigned_task_ids_.load(std::memory_order_relaxed); - uint32_t new_assigned_task_ids = 0; - int task_id = 0; - // memory_order_acquire on success, matched with memory_order_release in - // ReleaseTaskId() so that operations done by previous threads that had - // the same task_id become visible to the current thread. - do { - // Count trailing one bits. This is the id of the right-most 0-bit in - // |assigned_task_ids|. - task_id = std::countr_one(assigned_task_ids); - new_assigned_task_ids = assigned_task_ids | (uint32_t(1) << task_id); - } while (!assigned_task_ids_.compare_exchange_weak( - assigned_task_ids, new_assigned_task_ids, std::memory_order_acquire, - std::memory_order_relaxed)); - return static_cast(task_id); -} - -void JobTaskSourceOld::ReleaseTaskId(uint8_t task_id) { - // memory_order_release to match AcquireTaskId(). - uint32_t previous_task_ids = assigned_task_ids_.fetch_and( - ~(uint32_t(1) << task_id), std::memory_order_release); - DCHECK(previous_task_ids & (uint32_t(1) << task_id)); -} - -bool JobTaskSourceOld::ShouldYield() { - // It is safe to read |join_flag_| and |state_| without a lock since these - // variables are atomic, keeping in mind that threads may not immediately see - // the new value when it is updated. - return TS_UNCHECKED_READ(join_flag_).ShouldWorkerYield() || - TS_UNCHECKED_READ(state_).Load().is_canceled(); -} - -PooledTaskRunnerDelegate* JobTaskSourceOld::GetDelegate() const { - return delegate_; -} - -Task JobTaskSourceOld::TakeTask(TaskSource::Transaction* transaction) { - // JobTaskSource members are not lock-protected so no need to acquire a lock - // if |transaction| is nullptr. - DCHECK_GT(TS_UNCHECKED_READ(state_).Load().worker_count(), 0U); - DCHECK(primary_task_); - return {task_metadata_, primary_task_}; -} - -bool JobTaskSourceOld::DidProcessTask( - TaskSource::Transaction* /*transaction*/) { - // Lock is needed to access |join_flag_| below and signal - // |worker_released_condition_|. - CheckedAutoLock auto_lock(worker_lock_); - const auto state_before_sub = state_.DecrementWorkerCount(); - - if (join_flag_.ShouldWorkerSignal()) { - worker_released_condition_->Signal(); - } - - // A canceled task source should never get re-enqueued. - if (state_before_sub.is_canceled()) { - return false; - } - - DCHECK_GT(state_before_sub.worker_count(), 0U); - - // Re-enqueue the TaskSource if the task ran and the worker count is below the - // max concurrency. - // |worker_count - 1| to exclude the returning thread. - return state_before_sub.worker_count() <= - GetMaxConcurrency(state_before_sub.worker_count() - 1); -} - -// This is a no-op and should always return true. -bool JobTaskSourceOld::WillReEnqueue(TimeTicks now, - TaskSource::Transaction* /*transaction*/) { - return true; -} - -// This is a no-op. -bool JobTaskSourceOld::OnBecomeReady() { - return false; -} - -TaskSourceSortKey JobTaskSourceOld::GetSortKey() const { - return TaskSourceSortKey(priority_racy(), ready_time_, - TS_UNCHECKED_READ(state_).Load().worker_count()); -} - -// This function isn't expected to be called since a job is never delayed. -// However, the class still needs to provide an override. -TimeTicks JobTaskSourceOld::GetDelayedSortKey() const { - return TimeTicks(); -} - -// This function isn't expected to be called since a job is never delayed. -// However, the class still needs to provide an override. -bool JobTaskSourceOld::HasReadyTasks(TimeTicks now) const { - NOTREACHED(); - return true; -} - -absl::optional JobTaskSourceOld::Clear( - TaskSource::Transaction* transaction) { - Cancel(); - - // Nothing is cleared since other workers might still racily run tasks. For - // simplicity, the destructor will take care of it once all references are - // released. - return absl::nullopt; -} - -} // namespace internal -} // namespace base diff --git a/naiveproxy/src/base/task/thread_pool/job_task_source_old.h b/naiveproxy/src/base/task/thread_pool/job_task_source_old.h deleted file mode 100644 index efed0aee6c..0000000000 --- a/naiveproxy/src/base/task/thread_pool/job_task_source_old.h +++ /dev/null @@ -1,231 +0,0 @@ -// 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. - -#ifndef BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_OLD_H_ -#define BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_OLD_H_ - -#include - -#include -#include -#include -#include - -#include "base/base_export.h" -#include "base/functional/callback.h" -#include "base/memory/raw_ptr.h" -#include "base/synchronization/condition_variable.h" -#include "base/task/common/checked_lock.h" -#include "base/task/post_job.h" -#include "base/task/task_traits.h" -#include "base/task/thread_pool/job_task_source_interface.h" -#include "base/task/thread_pool/task.h" -#include "base/task/thread_pool/task_source.h" -#include "base/task/thread_pool/task_source_sort_key.h" - -namespace base { -namespace internal { - -class PooledTaskRunnerDelegate; - -// A JobTaskSource generates many Tasks from a single RepeatingClosure. -// -// Derived classes control the intended concurrency with GetMaxConcurrency(). -class BASE_EXPORT JobTaskSourceOld : public JobTaskSource { - public: - JobTaskSourceOld(const Location& from_here, - const TaskTraits& traits, - RepeatingCallback worker_task, - MaxConcurrencyCallback max_concurrency_callback, - PooledTaskRunnerDelegate* delegate); - JobTaskSourceOld(const JobTaskSource&) = delete; - JobTaskSourceOld& operator=(const JobTaskSourceOld&) = delete; - - // Called before the task source is enqueued to initialize task metadata. - void WillEnqueue(int sequence_num, TaskAnnotator& annotator) override; - - // Notifies this task source that max concurrency was increased, and the - // number of worker should be adjusted. - bool NotifyConcurrencyIncrease() override; - - // Informs this JobTaskSource that the current thread would like to join and - // contribute to running |worker_task|. Returns true if the joining thread can - // contribute (RunJoinTask() can be called), or false if joining was completed - // and all other workers returned because either there's no work remaining or - // Job was cancelled. - bool WillJoin() override; - - // Contributes to running |worker_task| and returns true if the joining thread - // can contribute again (RunJoinTask() can be called again), or false if - // joining was completed and all other workers returned because either there's - // no work remaining or Job was cancelled. This should be called only after - // WillJoin() or RunJoinTask() previously returned true. - bool RunJoinTask() override; - - // Cancels this JobTaskSource, causing all workers to yield and WillRunTask() - // to return RunStatus::kDisallowed. - void Cancel(TaskSource::Transaction* transaction = nullptr) override; - - // TaskSource: - ExecutionEnvironment GetExecutionEnvironment() override; - size_t GetRemainingConcurrency() const override; - TaskSourceSortKey GetSortKey() const override; - TimeTicks GetDelayedSortKey() const override; - bool HasReadyTasks(TimeTicks now) const override; - - bool IsActive() const override; - size_t GetWorkerCount() const override; - - // Returns the maximum number of tasks from this TaskSource that can run - // concurrently. - size_t GetMaxConcurrency() const override; - - uint8_t AcquireTaskId() override; - void ReleaseTaskId(uint8_t task_id) override; - - // Returns true if a worker should return from the worker task on the current - // thread ASAP. - bool ShouldYield() override; - - PooledTaskRunnerDelegate* GetDelegate() const override; - - private: - // Atomic internal state to track the number of workers running a task from - // this JobTaskSource and whether this JobTaskSource is canceled. All - // operations are performed with std::memory_order_relaxed as State is only - // ever modified under a lock or read atomically (optimistic read). - class State { - public: - static constexpr uint32_t kCanceledMask = 1; - static constexpr int kWorkerCountBitOffset = 1; - static constexpr uint32_t kWorkerCountIncrement = 1 - << kWorkerCountBitOffset; - - struct Value { - uint8_t worker_count() const { - return static_cast(value >> kWorkerCountBitOffset); - } - // Returns true if canceled. - bool is_canceled() const { return value & kCanceledMask; } - - uint32_t value; - }; - - State(); - ~State(); - - // Sets as canceled. Returns the state - // before the operation. - Value Cancel(); - - // Increments the worker count by 1. Returns the state before the operation. - Value IncrementWorkerCount(); - - // Decrements the worker count by 1. Returns the state before the operation. - Value DecrementWorkerCount(); - - // Loads and returns the state. - Value Load() const; - - private: - std::atomic value_{0}; - }; - - // Atomic flag that indicates if the joining thread is currently waiting on - // another worker to yield or to signal. - class JoinFlag { - public: - static constexpr uint32_t kNotWaiting = 0; - static constexpr uint32_t kWaitingForWorkerToSignal = 1; - static constexpr uint32_t kWaitingForWorkerToYield = 3; - // kWaitingForWorkerToYield is 3 because the impl relies on the following - // property. - static_assert((kWaitingForWorkerToYield & kWaitingForWorkerToSignal) == - kWaitingForWorkerToSignal, - ""); - - JoinFlag(); - ~JoinFlag(); - - // Returns true if the status is not kNotWaiting, using - // std::memory_order_relaxed. - bool IsWaiting() { - return value_.load(std::memory_order_relaxed) != kNotWaiting; - } - - // Resets the status as kNotWaiting using std::memory_order_relaxed. - void Reset(); - - // Sets the status as kWaitingForWorkerToYield using - // std::memory_order_relaxed. - void SetWaiting(); - - // If the flag is kWaitingForWorkerToYield, returns true indicating that the - // worker should yield, and atomically updates to kWaitingForWorkerToSignal - // (using std::memory_order_relaxed) to ensure that a single worker yields - // in response to SetWaiting(). - bool ShouldWorkerYield(); - - // If the flag is kWaiting*, returns true indicating that the worker should - // signal, and atomically updates to kNotWaiting (using - // std::memory_order_relaxed) to ensure that a single worker signals in - // response to SetWaiting(). - bool ShouldWorkerSignal(); - - private: - std::atomic value_{kNotWaiting}; - }; - - ~JobTaskSourceOld() override; - - // Called from the joining thread. Waits for the worker count to be below or - // equal to max concurrency (will happen when a worker calls - // DidProcessTask()). Returns true if the joining thread should run a task, or - // false if joining was completed and all other workers returned because - // either there's no work remaining or Job was cancelled. - bool WaitForParticipationOpportunity() EXCLUSIVE_LOCKS_REQUIRED(worker_lock_); - - size_t GetMaxConcurrency(size_t worker_count) const; - - // TaskSource: - RunStatus WillRunTask() override; - Task TakeTask(TaskSource::Transaction* transaction) override; - absl::optional Clear(TaskSource::Transaction* transaction) override; - bool DidProcessTask(TaskSource::Transaction* transaction) override; - bool WillReEnqueue(TimeTicks now, - TaskSource::Transaction* transaction) override; - bool OnBecomeReady() override; - - // Synchronizes access to workers state. - mutable CheckedLock worker_lock_{UniversalSuccessor()}; - - // Current atomic state (atomic despite the lock to allow optimistic reads - // and cancellation without the lock). - State state_ GUARDED_BY(worker_lock_); - // Normally, |join_flag_| is protected by |lock_|, except in ShouldYield() - // hence the use of atomics. - JoinFlag join_flag_ GUARDED_BY(worker_lock_); - // Signaled when |join_flag_| is kWaiting* and a worker returns. - std::unique_ptr worker_released_condition_ - GUARDED_BY(worker_lock_); - - std::atomic assigned_task_ids_{0}; - - RepeatingCallback max_concurrency_callback_; - - // Worker task set by the job owner. - RepeatingCallback worker_task_; - // Task returned from TakeTask(), that calls |worker_task_| internally. - RepeatingClosure primary_task_; - - TaskMetadata task_metadata_; - - const TimeTicks ready_time_; - raw_ptr delegate_; -}; - -} // namespace internal -} // namespace base - -#endif // BASE_TASK_THREAD_POOL_JOB_TASK_SOURCE_OLD_H_ diff --git a/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc b/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc index 3f73be42cf..2dd617d659 100644 --- a/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc +++ b/naiveproxy/src/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc @@ -823,7 +823,7 @@ void PooledSingleThreadTaskRunnerManager::UnregisterWorkerThread( return; auto worker_iter = ranges::find(workers_, worker); - DCHECK(worker_iter != workers_.end()); + CHECK(worker_iter != workers_.end(), base::NotFatalUntil::M125); worker_to_destroy = std::move(*worker_iter); workers_.erase(worker_iter); } diff --git a/naiveproxy/src/base/task/thread_pool/task_source.h b/naiveproxy/src/base/task/thread_pool/task_source.h index 0a012d3a48..42a6b2bcea 100644 --- a/naiveproxy/src/base/task/thread_pool/task_source.h +++ b/naiveproxy/src/base/task/thread_pool/task_source.h @@ -149,7 +149,7 @@ class BASE_EXPORT TaskSource : public RefCountedThreadSafe { private: friend class TaskSource; - raw_ptr task_source_; + raw_ptr task_source_; }; // |traits| is metadata that applies to all Tasks in the TaskSource. @@ -339,7 +339,7 @@ class BASE_EXPORT RegisteredTaskSource { #endif // DCHECK_IS_ON() scoped_refptr task_source_; - raw_ptr task_tracker_ = nullptr; + raw_ptr task_tracker_ = nullptr; }; // A pair of Transaction and RegisteredTaskSource. Useful to carry a diff --git a/naiveproxy/src/base/task/thread_pool/test_utils.cc b/naiveproxy/src/base/task/thread_pool/test_utils.cc index effc1ed61e..5a68a3f987 100644 --- a/naiveproxy/src/base/task/thread_pool/test_utils.cc +++ b/naiveproxy/src/base/task/thread_pool/test_utils.cc @@ -64,7 +64,8 @@ bool MockJobTaskRunner::PostDelayedTask(const Location& from_here, auto job_task = base::MakeRefCounted(std::move(closure)); scoped_refptr task_source = job_task->GetJobTaskSource( from_here, traits_, pooled_task_runner_delegate_); - return task_source->NotifyConcurrencyIncrease(); + return pooled_task_runner_delegate_->EnqueueJobTaskSource( + std::move(task_source)); } scoped_refptr CreateJobTaskRunner( @@ -312,7 +313,7 @@ scoped_refptr MockJobTask::GetJobTaskSource( const Location& from_here, const TaskTraits& traits, PooledTaskRunnerDelegate* delegate) { - return CreateJobTaskSource( + return MakeRefCounted( from_here, traits, base::BindRepeating(&test::MockJobTask::Run, this), base::BindRepeating(&test::MockJobTask::GetMaxConcurrency, this), delegate); diff --git a/naiveproxy/src/base/task/thread_pool/thread_group.cc b/naiveproxy/src/base/task/thread_pool/thread_group.cc index 38888cf044..91d68d6039 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_group.cc @@ -12,6 +12,7 @@ #include "base/functional/callback_helpers.h" #include "base/task/task_features.h" #include "base/task/thread_pool/task_tracker.h" +#include "base/task/thread_pool/thread_group_worker_delegate.h" #include "build/build_config.h" #include "third_party/abseil-cpp/absl/base/attributes.h" @@ -153,16 +154,25 @@ ThreadGroup::ThreadGroup(StringPiece histogram_label, DCHECK(!thread_group_label_.empty()); } -void ThreadGroup::Start( +void ThreadGroup::StartImpl( size_t max_tasks, size_t max_best_effort_tasks, TimeDelta suggested_reclaim_time, scoped_refptr service_thread_task_runner, WorkerThreadObserver* worker_thread_observer, WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing, absl::optional may_block_threshold) { DCHECK(!replacement_thread_group_); + if (synchronous_thread_start_for_testing) { + worker_started_for_testing_.emplace(WaitableEvent::ResetPolicy::AUTOMATIC); + // Don't emit a ScopedBlockingCallWithBaseSyncPrimitives from this + // WaitableEvent or it defeats the purpose of having threads start without + // externally visible side-effects. + worker_started_for_testing_->declare_only_used_while_idle(); + } + in_start().no_worker_reclaim = FeatureList::IsEnabled(kNoWorkerThreadReclaim); in_start().may_block_threshold = may_block_threshold ? may_block_threshold.value() @@ -173,15 +183,13 @@ void ThreadGroup::Start( thread_type_hint_ != ThreadType::kBackground ? kForegroundBlockedWorkersPoll : kBackgroundBlockedWorkersPoll; - in_start().ensure_enough_workers_at_end_of_get_work = - base::FeatureList::IsEnabled(kUseNewJobImplementation); + in_start().max_num_workers_created = base::kMaxNumWorkersCreated.Get(); CheckedAutoLock auto_lock(lock_); max_tasks_ = max_tasks; DCHECK_GE(max_tasks_, 1U); - in_start().initial_max_tasks = max_tasks_; - DCHECK_LE(in_start().initial_max_tasks, kMaxNumberOfWorkers); + in_start().initial_max_tasks = std::min(max_tasks_, kMaxNumberOfWorkers); max_best_effort_tasks_ = max_best_effort_tasks; in_start().suggested_reclaim_time = suggested_reclaim_time; in_start().worker_environment = worker_environment; @@ -353,11 +361,11 @@ void ThreadGroup::UpdateSortKeyImpl(BaseScopedCommandsExecutor* executor, void ThreadGroup::PushTaskSourceAndWakeUpWorkersImpl( BaseScopedCommandsExecutor* executor, RegisteredTaskSourceAndTransaction transaction_with_task_source) { - CheckedAutoLock auto_lock(lock_); DCHECK(!replacement_thread_group_); DCHECK_EQ(delegate_->GetThreadGroupForTraits( transaction_with_task_source.transaction.traits()), this); + CheckedAutoLock lock(lock_); if (transaction_with_task_source.task_source->immediate_heap_handle() .IsValid()) { // If the task source changed group, it is possible that multiple concurrent @@ -377,6 +385,27 @@ void ThreadGroup::PushTaskSourceAndWakeUpWorkersImpl( EnsureEnoughWorkersLockRequired(executor); } +void ThreadGroup::EnqueueAllTaskSources(PriorityQueue* new_priority_queue) { + std::unique_ptr executor = GetExecutor(); + CheckedAutoLock lock(lock_); + while (!new_priority_queue->IsEmpty()) { + TaskSourceSortKey top_sort_key = new_priority_queue->PeekSortKey(); + RegisteredTaskSource task_source = new_priority_queue->PopTaskSource(); + priority_queue_.Push(std::move(task_source), top_sort_key); + } +} + +void ThreadGroup::HandoffAllTaskSourcesToOtherThreadGroup( + ThreadGroup* destination_thread_group) { + PriorityQueue new_priority_queue; + TaskSourceSortKey top_sort_key; + { + CheckedAutoLock current_thread_group_lock(lock_); + new_priority_queue.swap(priority_queue_); + } + destination_thread_group->EnqueueAllTaskSources(&new_priority_queue); +} + void ThreadGroup::HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( ThreadGroup* destination_thread_group) { PriorityQueue new_priority_queue; @@ -391,18 +420,7 @@ void ThreadGroup::HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( } new_priority_queue.swap(priority_queue_); } - { - std::unique_ptr executor = - destination_thread_group->GetExecutor(); - CheckedAutoLock destination_thread_group_lock( - destination_thread_group->lock_); - while (!new_priority_queue.IsEmpty()) { - top_sort_key = new_priority_queue.PeekSortKey(); - RegisteredTaskSource task_source = new_priority_queue.PopTaskSource(); - destination_thread_group->priority_queue_.Push(std::move(task_source), - top_sort_key); - } - } + destination_thread_group->EnqueueAllTaskSources(&new_priority_queue); } bool ThreadGroup::ShouldYield(TaskSourceSortKey sort_key) { @@ -473,6 +491,47 @@ size_t ThreadGroup::GetMaxBestEffortTasksForTesting() const { return max_best_effort_tasks_; } +void ThreadGroup::WaitForWorkersIdleLockRequiredForTesting(size_t n) { + // Make sure workers do not cleanup while watching the idle count. + AutoReset ban_cleanups(&worker_cleanup_disallowed_for_testing_, true); + + while (NumberOfIdleWorkersLockRequiredForTesting() < n) { + idle_workers_set_cv_for_testing_->Wait(); + } +} + +void ThreadGroup::WaitForWorkersIdleForTesting(size_t n) { + CheckedAutoLock auto_lock(lock_); + +#if DCHECK_IS_ON() + DCHECK(!some_workers_cleaned_up_for_testing_) + << "Workers detached prior to waiting for a specific number of idle " + "workers. Doing the wait under such conditions is flaky. Consider " + "setting the suggested reclaim time to TimeDelta::Max() in Start()."; +#endif + + WaitForWorkersIdleLockRequiredForTesting(n); +} + +void ThreadGroup::WaitForAllWorkersIdleForTesting() { + CheckedAutoLock auto_lock(lock_); + WaitForWorkersIdleLockRequiredForTesting(workers_.size()); +} + +void ThreadGroup::WaitForWorkersCleanedUpForTesting(size_t n) { + CheckedAutoLock auto_lock(lock_); + + if (!num_workers_cleaned_up_for_testing_cv_) { + num_workers_cleaned_up_for_testing_cv_ = lock_.CreateConditionVariable(); + } + + while (num_workers_cleaned_up_for_testing_ < n) { + num_workers_cleaned_up_for_testing_cv_->Wait(); + } + + num_workers_cleaned_up_for_testing_ = 0; +} + size_t ThreadGroup::GetMaxConcurrentNonBlockedTasksDeprecated() const { #if DCHECK_IS_ON() CheckedAutoLock auto_lock(lock_); @@ -483,6 +542,16 @@ size_t ThreadGroup::GetMaxConcurrentNonBlockedTasksDeprecated() const { return after_start().initial_max_tasks; } +size_t ThreadGroup::NumberOfWorkersForTesting() const { + CheckedAutoLock auto_lock(lock_); + return workers_.size(); +} + +size_t ThreadGroup::NumberOfIdleWorkersForTesting() const { + CheckedAutoLock auto_lock(lock_); + return NumberOfIdleWorkersLockRequiredForTesting(); +} + size_t ThreadGroup::GetDesiredNumAwakeWorkersLockRequired() const { // Number of BEST_EFFORT task sources that are running or queued and allowed // to run by the CanRunPolicy. @@ -529,6 +598,51 @@ void ThreadGroup::ScheduleAdjustMaxTasks() { after_start().blocked_workers_poll_period); } +void ThreadGroup::AdjustMaxTasks() { + DCHECK( + after_start().service_thread_task_runner->RunsTasksInCurrentSequence()); + + std::unique_ptr executor = GetExecutor(); + CheckedAutoLock auto_lock(lock_); + DCHECK(adjust_max_tasks_posted_); + adjust_max_tasks_posted_ = false; + + // Increment max tasks for each worker that has been within a MAY_BLOCK + // ScopedBlockingCall for more than may_block_threshold. + for (scoped_refptr worker : workers_) { + // The delegates of workers inside a ThreadGroup should be + // WaitableEventWorkerDelegates. + ThreadGroupWorkerDelegate* delegate = GetWorkerDelegate(worker.get()); + AnnotateAcquiredLockAlias annotate(lock_, delegate->lock()); + delegate->MaybeIncrementMaxTasksLockRequired(); + } + + // Wake up workers according to the updated |max_tasks_|. This will also + // reschedule AdjustMaxTasks() if necessary. + EnsureEnoughWorkersLockRequired(executor.get()); +} + +void ThreadGroup::OnShutDownStartedImpl(BaseScopedCommandsExecutor* executor) { + CheckedAutoLock auto_lock(lock_); + + // Don't do anything if the thread group isn't started. + if (max_tasks_ == 0 || UNLIKELY(join_for_testing_started_)) { + return; + } + + // Start a MAY_BLOCK scope on each worker that is already running a task. + for (scoped_refptr& worker : workers_) { + // The delegates of workers inside a ThreadGroup should be + // WorkerThreadDelegateImpls. + ThreadGroupWorkerDelegate* delegate = GetWorkerDelegate(worker.get()); + AnnotateAcquiredLockAlias annotate(lock_, delegate->lock()); + delegate->OnShutdownStartedLockRequired(executor); + } + EnsureEnoughWorkersLockRequired(executor); + + shutdown_started_ = true; +} + bool ThreadGroup::ShouldPeriodicallyAdjustMaxTasksLockRequired() { // AdjustMaxTasks() should be scheduled to periodically adjust |max_tasks_| // and |max_best_effort_tasks_| when (1) the concurrency limits are not large diff --git a/naiveproxy/src/base/task/thread_pool/thread_group.h b/naiveproxy/src/base/task/thread_pool/thread_group.h index 5fba8c342c..ea9b1a3e53 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group.h +++ b/naiveproxy/src/base/task/thread_pool/thread_group.h @@ -66,6 +66,33 @@ class BASE_EXPORT ThreadGroup { ThreadGroup& operator=(const ThreadGroup&) = delete; virtual ~ThreadGroup(); + // Creates threads, allowing existing and future tasks to run. The thread + // group runs at most `max_tasks` / `max_best_effort_tasks` unblocked task + // with any / BEST_EFFORT priority concurrently. It reclaims unused threads + // after `suggested_reclaim_time`. It uses `service_thread_task_runner` to + // monitor for blocked tasks, `service_thread_task_runner` is used to setup + // FileDescriptorWatcher on worker threads. It must refer to a Thread with + // MessagePumpType::IO. If specified, it notifies `worker_thread_observer` + // when a worker enters and exits its main function (the observer must not be + // destroyed before JoinForTesting() has returned). `worker_environment` + // specifies the environment in which tasks are executed. + // `may_block_threshold` is the timeout after which a task in a MAY_BLOCK + // ScopedBlockingCall is considered blocked (the thread group will choose an + // appropriate value if none is specified). + // `synchronous_thread_start_for_testing` is true if this ThreadGroup should + // synchronously wait for OnMainEntry() after starting each worker. Can only + // be called once. CHECKs on failure. + virtual void Start( + size_t max_tasks, + size_t max_best_effort_tasks, + TimeDelta suggested_reclaim_time, + scoped_refptr service_thread_task_runner, + WorkerThreadObserver* worker_thread_observer, + WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing = false, + absl::optional may_block_threshold = + absl::optional()) = 0; + // Registers the thread group in TLS. void BindToCurrentThread(); @@ -96,6 +123,10 @@ class BASE_EXPORT ThreadGroup { virtual void PushTaskSourceAndWakeUpWorkers( RegisteredTaskSourceAndTransaction transaction_with_task_source) = 0; + // Move all task sources from this ThreadGroup's PriorityQueue to the + // |destination_thread_group|'s. + void HandoffAllTaskSourcesToOtherThreadGroup( + ThreadGroup* destination_thread_group); // Move all task sources except the ones with TaskPriority::USER_BLOCKING, // from this ThreadGroup's PriorityQueue to the |destination_thread_group|'s. void HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( @@ -136,6 +167,34 @@ class BASE_EXPORT ThreadGroup { size_t GetMaxTasksForTesting() const; size_t GetMaxBestEffortTasksForTesting() const; + // Waits until at least |n| workers are idle. Note that while workers are + // disallowed from cleaning up during this call: tests using a custom + // |suggested_reclaim_time_| need to be careful to invoke this swiftly after + // unblocking the waited upon workers as: if a worker is already detached by + // the time this is invoked, it will never make it onto the idle set and + // this call will hang. + void WaitForWorkersIdleForTesting(size_t n); + + // Waits until at least |n| workers are idle. + void WaitForWorkersIdleLockRequiredForTesting(size_t n) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // Waits until all workers are idle. + void WaitForAllWorkersIdleForTesting(); + + // Waits until |n| workers have cleaned up (went through + // WorkerThread::Delegate::OnMainExit()) since the last call to + // WaitForWorkersCleanedUpForTesting() (or Start() if that wasn't called yet). + void WaitForWorkersCleanedUpForTesting(size_t n); + + // Returns the number of workers in this thread group. + size_t NumberOfWorkersForTesting() const; + // Returns the number of workers that are idle (i.e. not running tasks). + size_t NumberOfIdleWorkersForTesting() const; + // Returns the number of workers that are idle (i.e. not running tasks). + virtual size_t NumberOfIdleWorkersLockRequiredForTesting() const + EXCLUSIVE_LOCKS_REQUIRED(lock_) = 0; + class ThreadGroupWorkerDelegate; protected: @@ -145,14 +204,16 @@ class BASE_EXPORT ThreadGroup { TrackedRef task_tracker, TrackedRef delegate); - void Start(size_t max_tasks, - size_t max_best_effort_tasks, - TimeDelta suggested_reclaim_time, - scoped_refptr service_thread_task_runner, - WorkerThreadObserver* worker_thread_observer, - WorkerEnvironment worker_environment, - absl::optional may_block_threshold = - absl::optional()); + void StartImpl( + size_t max_tasks, + size_t max_best_effort_tasks, + TimeDelta suggested_reclaim_time, + scoped_refptr service_thread_task_runner, + WorkerThreadObserver* worker_thread_observer, + WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing = false, + absl::optional may_block_threshold = + absl::optional()); // Derived classes must implement a ScopedCommandsExecutor that derives from // this to perform operations at the end of a scope, when all locks have been @@ -258,6 +319,10 @@ class BASE_EXPORT ThreadGroup { void PushTaskSourceAndWakeUpWorkersImpl( BaseScopedCommandsExecutor* executor, RegisteredTaskSourceAndTransaction transaction_with_task_source); + void OnShutDownStartedImpl(BaseScopedCommandsExecutor* executor); + + virtual ThreadGroupWorkerDelegate* GetWorkerDelegate( + WorkerThread* worker) = 0; // Returns the desired number of awake workers, given current workload and // concurrency limits. @@ -267,12 +332,15 @@ class BASE_EXPORT ThreadGroup { // Examines the list of WorkerThreads and increments |max_tasks_| for each // worker that has been within the scope of a MAY_BLOCK ScopedBlockingCall for // more than BlockedThreshold(). Reschedules a call if necessary. - virtual void AdjustMaxTasks() = 0; + void AdjustMaxTasks(); // Schedules AdjustMaxTasks() if required. void MaybeScheduleAdjustMaxTasksLockRequired( BaseScopedCommandsExecutor* executor) EXCLUSIVE_LOCKS_REQUIRED(lock_); + // Enqueues all task sources from `new_priority_queue` into this thread group. + void EnqueueAllTaskSources(PriorityQueue* new_priority_queue); + // Returns the threshold after which the max tasks is increased to compensate // for a worker that is within a MAY_BLOCK ScopedBlockingCall. TimeDelta may_block_threshold_for_testing() const { @@ -349,9 +417,9 @@ class BASE_EXPORT ThreadGroup { // capacity. TimeDelta blocked_workers_poll_period; - // Whether EnsureEnoughWorkersLockRequired() should be called at the end of - // GetWork() instead of at the beginning. - bool ensure_enough_workers_at_end_of_get_work = false; + // The max number of workers that a ThreadGroupSemaphore will create in any + // one EnsureEnoughWorkers() call. + int max_num_workers_created = 2; } initialized_in_start_; InitializedInStart& in_start() { @@ -455,13 +523,16 @@ class BASE_EXPORT ThreadGroup { std::unique_ptr num_workers_cleaned_up_for_testing_cv_ GUARDED_BY(lock_); - // Set at the start of JoinForTesting(). - bool join_for_testing_started_ GUARDED_BY(lock_) = false; + // All workers owned by this thread group. + std::vector> workers_ GUARDED_BY(lock_); // Null-opt unless |synchronous_thread_start_for_testing| was true at // construction. In that case, it's signaled each time // WorkerThreadDelegateImpl::OnMainEntry() completes. absl::optional worker_started_for_testing_; + + // Set at the start of JoinForTesting(). + bool join_for_testing_started_ GUARDED_BY(lock_) = false; }; } // namespace internal diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc b/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc index c8e906d6b4..cb0abdf821 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_group_impl.cc @@ -8,7 +8,7 @@ #include "base/metrics/histogram_macros.h" #include "base/sequence_token.h" #include "base/strings/string_piece.h" -#include "base/strings/stringprintf.h" +#include "base/task/common/checked_lock.h" #include "base/task/thread_pool/thread_group_worker_delegate.h" #include "base/task/thread_pool/worker_thread_waitable_event.h" #include "base/threading/scoped_blocking_call.h" @@ -82,8 +82,6 @@ class ThreadGroupImpl::WaitableEventWorkerDelegate // WorkerThreadWaitableEvent::Delegate: void RecordUnnecessaryWakeup() override; - // True if the calling worker is be eligible for reclaim. - bool IsExcess() const override; TimeDelta GetSleepTimeout() override; private: @@ -102,16 +100,10 @@ class ThreadGroupImpl::WaitableEventWorkerDelegate WorkerThread* worker) EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; - RegisteredTaskSource GetWorkLockRequired(ScopedCommandsExecutor* executor, - WorkerThreadWaitableEvent* worker) - EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_); - // Returns true if |worker| is allowed to cleanup and remove itself from the // thread group. Called from GetWork() when no work is available. bool CanCleanupLockRequired(const WorkerThread* worker) EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; - - const bool is_excess_; }; std::unique_ptr @@ -130,7 +122,6 @@ ThreadGroupImpl::ThreadGroupImpl(StringPiece histogram_label, thread_type_hint, std::move(task_tracker), std::move(delegate)), - idle_workers_set_cv_for_testing_(lock_.CreateConditionVariable()), tracked_ref_factory_(this) { DCHECK(!thread_group_label_.empty()); } @@ -144,17 +135,10 @@ void ThreadGroupImpl::Start( WorkerEnvironment worker_environment, bool synchronous_thread_start_for_testing, absl::optional may_block_threshold) { - ThreadGroup::Start(max_tasks, max_best_effort_tasks, suggested_reclaim_time, - service_thread_task_runner, worker_thread_observer, - worker_environment, may_block_threshold); - - if (synchronous_thread_start_for_testing) { - worker_started_for_testing_.emplace(WaitableEvent::ResetPolicy::AUTOMATIC); - // Don't emit a ScopedBlockingCallWithBaseSyncPrimitives from this - // WaitableEvent or it defeats the purpose of having threads start without - // externally visible side-effects. - worker_started_for_testing_->declare_only_used_while_idle(); - } + ThreadGroup::StartImpl( + max_tasks, max_best_effort_tasks, suggested_reclaim_time, + service_thread_task_runner, worker_thread_observer, worker_environment, + synchronous_thread_start_for_testing, may_block_threshold); ScopedCommandsExecutor executor(this); CheckedAutoLock auto_lock(lock_); @@ -182,51 +166,10 @@ void ThreadGroupImpl::PushTaskSourceAndWakeUpWorkers( std::move(transaction_with_task_source)); } -void ThreadGroupImpl::WaitForWorkersIdleLockRequiredForTesting(size_t n) { - // Make sure workers do not cleanup while watching the idle count. - AutoReset ban_cleanups(&worker_cleanup_disallowed_for_testing_, true); - - while (idle_workers_set_.Size() < n) { - idle_workers_set_cv_for_testing_->Wait(); - } -} - -void ThreadGroupImpl::WaitForWorkersIdleForTesting(size_t n) { - CheckedAutoLock auto_lock(lock_); - -#if DCHECK_IS_ON() - DCHECK(!some_workers_cleaned_up_for_testing_) - << "Workers detached prior to waiting for a specific number of idle " - "workers. Doing the wait under such conditions is flaky. Consider " - "setting the suggested reclaim time to TimeDelta::Max() in Start()."; -#endif - - WaitForWorkersIdleLockRequiredForTesting(n); -} - -void ThreadGroupImpl::WaitForAllWorkersIdleForTesting() { - CheckedAutoLock auto_lock(lock_); - WaitForWorkersIdleLockRequiredForTesting(workers_.size()); -} - -void ThreadGroupImpl::WaitForWorkersCleanedUpForTesting(size_t n) { - CheckedAutoLock auto_lock(lock_); - - if (!num_workers_cleaned_up_for_testing_cv_) { - num_workers_cleaned_up_for_testing_cv_ = lock_.CreateConditionVariable(); - } - - while (num_workers_cleaned_up_for_testing_ < n) { - num_workers_cleaned_up_for_testing_cv_->Wait(); - } - - num_workers_cleaned_up_for_testing_ = 0; -} - ThreadGroupImpl::WaitableEventWorkerDelegate::WaitableEventWorkerDelegate( TrackedRef outer, bool is_excess) - : ThreadGroupWorkerDelegate(std::move(outer)), is_excess_(is_excess) { + : ThreadGroupWorkerDelegate(std::move(outer), is_excess) { // Bound in OnMainEntry(). DETACH_FROM_THREAD(worker_thread_checker_); } @@ -237,36 +180,7 @@ TimeDelta ThreadGroupImpl::WaitableEventWorkerDelegate::GetSleepTimeout() { void ThreadGroupImpl::WaitableEventWorkerDelegate::OnMainEntry( WorkerThread* worker) { - DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); - - { -#if DCHECK_IS_ON() - CheckedAutoLock auto_lock(outer()->lock_); - DCHECK(ContainsWorker(outer()->workers_, - static_cast(worker))); -#endif - } - -#if BUILDFLAG(IS_WIN) - worker_only().win_thread_environment = GetScopedWindowsThreadEnvironment( - outer()->after_start().worker_environment); -#endif // BUILDFLAG(IS_WIN) - - PlatformThread::SetName( - StringPrintf("ThreadPool%sWorker", outer()->thread_group_label_.c_str())); - - outer()->BindToCurrentThread(); - worker_only().worker_thread_ = - static_cast(worker); - SetBlockingObserverForCurrentThread(this); - - if (outer()->worker_started_for_testing_) { - // When |worker_started_for_testing_| is set, the thread that starts workers - // should wait for a worker to have started before starting the next one, - // and there should only be one thread that wakes up workers at a time. - DCHECK(!outer()->worker_started_for_testing_->IsSignaled()); - outer()->worker_started_for_testing_->Signal(); - } + OnMainEntryImpl(worker); } void ThreadGroupImpl::WaitableEventWorkerDelegate::OnMainExit( @@ -341,89 +255,16 @@ bool ThreadGroupImpl::WaitableEventWorkerDelegate::CanGetWorkLockRequired( return true; } -RegisteredTaskSource -ThreadGroupImpl::WaitableEventWorkerDelegate::GetWorkLockRequired( - ScopedCommandsExecutor* executor, - WorkerThreadWaitableEvent* worker) { - DCHECK(ContainsWorker(outer()->workers_, worker)); - - if (!outer()->after_start().ensure_enough_workers_at_end_of_get_work) { - // Use this opportunity, before assigning work to this worker, to - // create/wake additional workers if needed (doing this here allows us to - // reduce potentially expensive create/wake directly on PostTask()). - // - // Note: FlushWorkerCreation() below releases |outer()->lock_|. It is thus - // important that all other operations come after it to keep this method - // transactional. - outer()->EnsureEnoughWorkersLockRequired(executor); - executor->FlushWorkerCreation(&outer()->lock_); - } - - if (!CanGetWorkLockRequired(executor, worker)) { - return nullptr; - } - - RegisteredTaskSource task_source; - TaskPriority priority; - while (!task_source && !outer()->priority_queue_.IsEmpty()) { - // Enforce the CanRunPolicy and that no more than |max_best_effort_tasks_| - // BEST_EFFORT tasks run concurrently. - priority = outer()->priority_queue_.PeekSortKey().priority(); - if (!outer()->task_tracker_->CanRunPriority(priority) || - (priority == TaskPriority::BEST_EFFORT && - outer()->num_running_best_effort_tasks_ >= - outer()->max_best_effort_tasks_)) { - break; - } - - task_source = outer()->TakeRegisteredTaskSource(executor); - } - if (!task_source) { - OnWorkerBecomesIdleLockRequired(executor, worker); - return nullptr; - } - - // Running task bookkeeping. - outer()->IncrementTasksRunningLockRequired(priority); - DCHECK(!outer()->idle_workers_set_.Contains(worker)); - - AnnotateAcquiredLockAlias annotate(outer()->lock_, lock()); - write_worker().current_task_priority = priority; - write_worker().current_shutdown_behavior = task_source->shutdown_behavior(); - - if (outer()->after_start().ensure_enough_workers_at_end_of_get_work) { - // Subtle: This must be after the call to WillRunTask() inside - // TakeRegisteredTaskSource(), so that any state used by WillRunTask() to - // determine that the task source must remain in the TaskQueue is also used - // to determine the desired number of workers. Concretely, this wouldn't - // work: - // - // Thread 1: GetWork() calls EnsureEnoughWorkers(). No worker woken up - // because the queue contains a job with max concurrency = 1 and - // the current worker is awake. - // Thread 2: Increases the job's max concurrency. - // ShouldQueueUponCapacityIncrease() returns false because the - // job is already queued. - // Thread 1: Calls WillRunTask() on the job. It returns - // kAllowedNotSaturated because max concurrency is not reached. - // But no extra worker is woken up to run the job! - outer()->EnsureEnoughWorkersLockRequired(executor); - } - - return task_source; -} - RegisteredTaskSource ThreadGroupImpl::WaitableEventWorkerDelegate::GetWork( - WorkerThread* worker_base) { + WorkerThread* worker) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); DCHECK(!read_worker().current_task_priority); DCHECK(!read_worker().current_shutdown_behavior); - WorkerThreadWaitableEvent* worker = - static_cast(worker_base); ScopedCommandsExecutor executor(outer()); CheckedAutoLock auto_lock(outer()->lock_); - + AnnotateAcquiredLockAlias alias( + outer()->lock_, static_cast(outer_.get())->lock_); return GetWorkLockRequired(&executor, worker); } @@ -491,14 +332,10 @@ ThreadGroupImpl::WaitableEventWorkerDelegate::SwapProcessedTask( static_cast(worker)); } -bool ThreadGroupImpl::WaitableEventWorkerDelegate::IsExcess() const { - return is_excess_; -} - bool ThreadGroupImpl::WaitableEventWorkerDelegate::CanCleanupLockRequired( const WorkerThread* worker) { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); - if (!IsExcess()) { + if (!is_excess_) { return false; } @@ -525,7 +362,7 @@ void ThreadGroupImpl::WaitableEventWorkerDelegate::CleanupLockRequired( // Remove the worker from |workers_|. auto worker_iter = ranges::find(outer()->workers_, worker); - DCHECK(worker_iter != outer()->workers_.end()); + CHECK(worker_iter != outer()->workers_.end(), base::NotFatalUntil::M125); outer()->workers_.erase(worker_iter); } @@ -545,12 +382,7 @@ void ThreadGroupImpl::WaitableEventWorkerDelegate:: } void ThreadGroupImpl::WaitableEventWorkerDelegate::RecordUnnecessaryWakeup() { - base::BooleanHistogram::FactoryGet( - std::string("ThreadPool.UnnecessaryWakeup.") + outer()->histogram_label_, - base::Histogram::kUmaTargetedHistogramFlag) - ->Add(true); - - TRACE_EVENT_INSTANT("wakeup.flow", "ThreadPool.UnnecessaryWakeup"); + RecordUnnecessaryWakeupImpl(); } void ThreadGroupImpl::JoinForTesting() { @@ -574,7 +406,7 @@ void ThreadGroupImpl::JoinForTesting() { workers_copy = workers_; } for (const auto& worker : workers_copy) { - worker->JoinForTesting(); + static_cast(worker.get())->JoinForTesting(); } CheckedAutoLock auto_lock(lock_); @@ -583,13 +415,7 @@ void ThreadGroupImpl::JoinForTesting() { workers_.clear(); } -size_t ThreadGroupImpl::NumberOfWorkersForTesting() const { - CheckedAutoLock auto_lock(lock_); - return workers_.size(); -} - -size_t ThreadGroupImpl::NumberOfIdleWorkersForTesting() const { - CheckedAutoLock auto_lock(lock_); +size_t ThreadGroupImpl::NumberOfIdleWorkersLockRequiredForTesting() const { return idle_workers_set_.Size(); } @@ -655,27 +481,15 @@ void ThreadGroupImpl::DidUpdateCanRunPolicy() { EnsureEnoughWorkersLockRequired(&executor); } +ThreadGroup::ThreadGroupWorkerDelegate* ThreadGroupImpl::GetWorkerDelegate( + WorkerThread* worker) { + return static_cast( + static_cast(worker->delegate())); +} + void ThreadGroupImpl::OnShutdownStarted() { ScopedCommandsExecutor executor(this); - CheckedAutoLock auto_lock(lock_); - - // Don't do anything if the thread group isn't started. - if (max_tasks_ == 0 || UNLIKELY(join_for_testing_started_)) { - return; - } - - // Start a MAY_BLOCK scope on each worker that is already running a task. - for (scoped_refptr& worker : workers_) { - // The delegates of workers inside a ThreadGroup should be - // WorkerThreadDelegateImpls. - WaitableEventWorkerDelegate* delegate = - static_cast(worker->delegate()); - AnnotateAcquiredLockAlias annotate(lock_, delegate->lock()); - delegate->OnShutdownStartedLockRequired(&executor); - } - EnsureEnoughWorkersLockRequired(&executor); - - shutdown_started_ = true; + OnShutDownStartedImpl(&executor); } void ThreadGroupImpl::EnsureEnoughWorkersLockRequired( @@ -720,31 +534,6 @@ void ThreadGroupImpl::EnsureEnoughWorkersLockRequired( MaybeScheduleAdjustMaxTasksLockRequired(executor); } -void ThreadGroupImpl::AdjustMaxTasks() { - DCHECK( - after_start().service_thread_task_runner->RunsTasksInCurrentSequence()); - - ScopedCommandsExecutor executor(this); - CheckedAutoLock auto_lock(lock_); - DCHECK(adjust_max_tasks_posted_); - adjust_max_tasks_posted_ = false; - - // Increment max tasks for each worker that has been within a MAY_BLOCK - // ScopedBlockingCall for more than may_block_threshold. - for (scoped_refptr worker : workers_) { - // The delegates of workers inside a ThreadGroup should be - // WaitableEventWorkerDelegates. - WaitableEventWorkerDelegate* delegate = - static_cast(worker->delegate()); - AnnotateAcquiredLockAlias annotate(lock_, delegate->lock()); - delegate->MaybeIncrementMaxTasksLockRequired(); - } - - // Wake up workers according to the updated |max_tasks_|. This will also - // reschedule AdjustMaxTasks() if necessary. - EnsureEnoughWorkersLockRequired(&executor); -} - bool ThreadGroupImpl::IsOnIdleSetLockRequired( WorkerThreadWaitableEvent* worker) const { // To avoid searching through the idle set : use GetLastUsedTime() not being diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_impl.h b/naiveproxy/src/base/task/thread_pool/thread_group_impl.h index 74a4cc2d7e..e2edf28f48 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group_impl.h +++ b/naiveproxy/src/base/task/thread_pool/thread_group_impl.h @@ -51,32 +51,6 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { TrackedRef task_tracker, TrackedRef delegate); - // Creates threads, allowing existing and future tasks to run. The thread - // group runs at most |max_tasks| / `max_best_effort_tasks` unblocked task - // with any / BEST_EFFORT priority concurrently. It reclaims unused threads - // after `suggested_reclaim_time`. It uses `service_thread_task_runner` to - // monitor for blocked tasks, `service_thread_task_runner` is used to setup - // FileDescriptorWatcher on worker threads. It must refer to a Thread with - // MessagePumpType::IO. If specified, it notifies |worker_thread_observer| - // when a worker enters and exits its main function (the observer must not be - // destroyed before JoinForTesting() has returned). |worker_environment| - // specifies the environment in which tasks are executed. - // |may_block_threshold| is the timeout after which a task in a MAY_BLOCK - // ScopedBlockingCall is considered blocked (the thread group will choose an - // appropriate value if none is specified). - // `synchronous_thread_start_for_testing` is true if this ThreadGroup - // should synchronously wait for OnMainEntry() after starting each worker. Can - // only be called once. CHECKs on failure. - void Start(size_t max_tasks, - size_t max_best_effort_tasks, - TimeDelta suggested_reclaim_time, - scoped_refptr service_thread_task_runner, - WorkerThreadObserver* worker_thread_observer, - WorkerEnvironment worker_environment, - bool synchronous_thread_start_for_testing = false, - absl::optional may_block_threshold = - absl::optional()); - ThreadGroupImpl(const ThreadGroupImpl&) = delete; ThreadGroupImpl& operator=(const ThreadGroupImpl&) = delete; // Destroying a ThreadGroupImpl returned by Create() is not allowed @@ -85,39 +59,28 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { ~ThreadGroupImpl() override; // ThreadGroup: + void Start(size_t max_tasks, + size_t max_best_effort_tasks, + TimeDelta suggested_reclaim_time, + scoped_refptr service_thread_task_runner, + WorkerThreadObserver* worker_thread_observer, + WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing = false, + absl::optional may_block_threshold = + absl::optional()) override; void JoinForTesting() override; void DidUpdateCanRunPolicy() override; void OnShutdownStarted() override; std::unique_ptr GetExecutor() override; - - // Waits until at least |n| workers are idle. Note that while workers are - // disallowed from cleaning up during this call: tests using a custom - // |suggested_reclaim_time_| need to be careful to invoke this swiftly after - // unblocking the waited upon workers as: if a worker is already detached by - // the time this is invoked, it will never make it onto the idle set and - // this call will hang. - void WaitForWorkersIdleForTesting(size_t n); - - // Waits until at least |n| workers are idle. - void WaitForWorkersIdleLockRequiredForTesting(size_t n) - EXCLUSIVE_LOCKS_REQUIRED(lock_); - - // Waits until all workers are idle. - void WaitForAllWorkersIdleForTesting(); - - // Waits until |n| workers have cleaned up (went through - // WaitableEventWorkerDelegate::OnMainExit()) since the last call to - // WaitForWorkersCleanedUpForTesting() (or Start() if that wasn't called yet). - void WaitForWorkersCleanedUpForTesting(size_t n); - - // Returns the number of workers in this thread group. - size_t NumberOfWorkersForTesting() const; // Returns the number of workers that are idle (i.e. not running tasks). - size_t NumberOfIdleWorkersForTesting() const; + size_t NumberOfIdleWorkersLockRequiredForTesting() const + EXCLUSIVE_LOCKS_REQUIRED(lock_) override; + protected: private: class ScopedCommandsExecutor; class WaitableEventWorkerDelegate; + friend class WaitableEventWorkerDelegate; // friend tests so that they can access |blocked_workers_poll_period| and // may_block_threshold(), both in ThreadGroup. @@ -134,7 +97,8 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { RegisteredTaskSourceAndTransaction transaction_with_task_source) override; void EnsureEnoughWorkersLockRequired(BaseScopedCommandsExecutor* executor) override EXCLUSIVE_LOCKS_REQUIRED(lock_); - void AdjustMaxTasks() override; + ThreadGroupWorkerDelegate* GetWorkerDelegate(WorkerThread* worker) override; + // Creates a worker and schedules its start, if needed, to maintain one idle // worker, |max_tasks_| permitting. void MaintainAtLeastOneIdleWorkerLockRequired( @@ -154,9 +118,6 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { bool IsOnIdleSetLockRequired(WorkerThreadWaitableEvent* worker) const EXCLUSIVE_LOCKS_REQUIRED(lock_); - // All workers owned by this thread group. - std::vector> workers_ - GUARDED_BY(lock_); size_t worker_sequence_num_ GUARDED_BY(lock_) = 0; // Ordered set of idle workers; the order uses pointer comparison, this is @@ -167,18 +128,6 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup { // is inserted on this set when it receives nullptr from GetWork(). WorkerThreadSet idle_workers_set_ GUARDED_BY(lock_); - // Signaled when a worker is added to the idle workers set. - std::unique_ptr idle_workers_set_cv_for_testing_ - GUARDED_BY(lock_); - - // Signaled, if non-null, when |num_workers_cleaned_up_for_testing_| is - // incremented. - std::unique_ptr num_workers_cleaned_up_for_testing_cv_ - GUARDED_BY(lock_); - - // Set at the start of JoinForTesting(). - bool join_for_testing_started_ GUARDED_BY(lock_) = false; - // Ensures recently cleaned up workers (ref. // WaitableEventWorkerDelegate::CleanupLockRequired()) had time to exit as // they have a raw reference to |this| (and to TaskTracker) which can diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.cc b/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.cc new file mode 100644 index 0000000000..0440a6c2be --- /dev/null +++ b/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.cc @@ -0,0 +1,515 @@ +// Copyright 2024 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/task/thread_pool/thread_group_semaphore.h" + +#include + +#include "base/metrics/histogram_macros.h" +#include "base/sequence_token.h" +#include "base/strings/string_piece.h" +#include "base/strings/stringprintf.h" +#include "base/task/common/checked_lock.h" +#include "base/task/thread_pool/thread_group.h" +#include "base/task/thread_pool/worker_thread_semaphore.h" +#include "base/threading/scoped_blocking_call.h" +#include "base/threading/scoped_blocking_call_internal.h" +#include "base/threading/thread_checker.h" +#include "base/time/time_override.h" +#include "base/trace_event/base_tracing.h" + +namespace base { +namespace internal { + +namespace { +constexpr size_t kMaxNumberOfWorkers = 256; +} // namespace + +// Upon destruction, executes actions that control the number of active workers. +// Useful to satisfy locking requirements of these actions. +class ThreadGroupSemaphore::SemaphoreScopedCommandsExecutor + : public ThreadGroup::BaseScopedCommandsExecutor { + public: + explicit SemaphoreScopedCommandsExecutor(ThreadGroupSemaphore* outer) + : BaseScopedCommandsExecutor(outer) {} + + SemaphoreScopedCommandsExecutor(const SemaphoreScopedCommandsExecutor&) = + delete; + SemaphoreScopedCommandsExecutor& operator=( + const SemaphoreScopedCommandsExecutor&) = delete; + ~SemaphoreScopedCommandsExecutor() override { + CheckedLock::AssertNoLockHeldOnCurrentThread(); + for (int i = 0; i < semaphore_signal_count_; ++i) { + TRACE_EVENT_INSTANT("wakeup.flow", "WorkerThreadSemaphore::Signal", + perfetto::Flow::FromPointer(&outer()->semaphore_)); + outer()->semaphore_.Signal(); + } + } + + void ScheduleSignal() EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) { + ++semaphore_signal_count_; + ++outer()->num_active_signals_; + } + + private: + friend class ThreadGroupSemaphore; + + ThreadGroupSemaphore* outer() { + return static_cast(outer_); + } + + int semaphore_signal_count_ = 0; +}; + +class ThreadGroupSemaphore::SemaphoreWorkerDelegate + : public ThreadGroup::ThreadGroupWorkerDelegate, + public WorkerThreadSemaphore::Delegate { + public: + // `outer` owns the worker for which this delegate is + // constructed. `join_called_for_testing` is shared amongst workers, and + // owned by `outer`. + explicit SemaphoreWorkerDelegate(TrackedRef outer, + bool is_excess, + AtomicFlag* join_called_for_testing); + SemaphoreWorkerDelegate(const SemaphoreWorkerDelegate&) = delete; + SemaphoreWorkerDelegate& operator=(const SemaphoreWorkerDelegate&) = delete; + + // OnMainExit() handles the thread-affine cleanup; + // SemaphoreWorkerDelegate can thereafter safely be deleted from any thread. + ~SemaphoreWorkerDelegate() override = default; + + // WorkerThread::Delegate: + void OnMainEntry(WorkerThread* worker) override; + void OnMainExit(WorkerThread* worker) override; + RegisteredTaskSource GetWork(WorkerThread* worker) override; + RegisteredTaskSource SwapProcessedTask(RegisteredTaskSource task_source, + WorkerThread* worker) override; + void RecordUnnecessaryWakeup() override; + TimeDelta GetSleepTimeout() override; + + private: + const ThreadGroupSemaphore* outer() const { + return static_cast(outer_.get()); + } + ThreadGroupSemaphore* outer() { + return static_cast(outer_.get()); + } + + // ThreadGroup::ThreadGroupWorkerDelegate: + bool CanGetWorkLockRequired(BaseScopedCommandsExecutor* executor, + WorkerThread* worker) + EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; + void CleanupLockRequired(BaseScopedCommandsExecutor* executor, + WorkerThread* worker) + EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; + void OnWorkerBecomesIdleLockRequired(BaseScopedCommandsExecutor* executor, + WorkerThread* worker) + EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; + + // Returns true if `worker` is allowed to cleanup and remove itself from the + // thread group. Called from GetWork() when no work is available. + bool CanCleanupLockRequired(const WorkerThread* worker) + EXCLUSIVE_LOCKS_REQUIRED(outer()->lock_) override; +}; + +std::unique_ptr +ThreadGroupSemaphore::GetExecutor() { + return std::make_unique(this); +} + +ThreadGroupSemaphore::ThreadGroupSemaphore(StringPiece histogram_label, + StringPiece thread_group_label, + ThreadType thread_type_hint, + TrackedRef task_tracker, + TrackedRef delegate) + : ThreadGroup(histogram_label, + thread_group_label, + thread_type_hint, + std::move(task_tracker), + std::move(delegate)), + tracked_ref_factory_(this) { + DCHECK(!thread_group_label_.empty()); +} + +void ThreadGroupSemaphore::Start( + size_t max_tasks, + size_t max_best_effort_tasks, + TimeDelta suggested_reclaim_time, + scoped_refptr service_thread_task_runner, + WorkerThreadObserver* worker_thread_observer, + WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing, + absl::optional may_block_threshold) { + ThreadGroup::StartImpl( + max_tasks, max_best_effort_tasks, suggested_reclaim_time, + service_thread_task_runner, worker_thread_observer, worker_environment, + synchronous_thread_start_for_testing, may_block_threshold); + + SemaphoreScopedCommandsExecutor executor(this); + CheckedAutoLock auto_lock(lock_); + DCHECK(workers_.empty()); + EnsureEnoughWorkersLockRequired(&executor); +} + +ThreadGroupSemaphore::~ThreadGroupSemaphore() { + // ThreadGroup should only ever be deleted: + // 1) In tests, after JoinForTesting(). + // 2) In production, iff initialization failed. + // In both cases `workers_` should be empty. + DCHECK(workers_.empty()); +} + +void ThreadGroupSemaphore::UpdateSortKey(TaskSource::Transaction transaction) { + SemaphoreScopedCommandsExecutor executor(this); + UpdateSortKeyImpl(&executor, std::move(transaction)); +} + +void ThreadGroupSemaphore::PushTaskSourceAndWakeUpWorkers( + RegisteredTaskSourceAndTransaction transaction_with_task_source) { + SemaphoreScopedCommandsExecutor executor(this); + PushTaskSourceAndWakeUpWorkersImpl(&executor, + std::move(transaction_with_task_source)); +} + +size_t ThreadGroupSemaphore::NumberOfIdleWorkersLockRequiredForTesting() const { + return static_cast( + ClampSub(static_cast(workers_.size()), + static_cast(num_active_signals_))); +} + +ThreadGroupSemaphore::SemaphoreWorkerDelegate::SemaphoreWorkerDelegate( + TrackedRef outer, + bool is_excess, + AtomicFlag* join_called_for_testing) + : ThreadGroupWorkerDelegate(std::move(outer), is_excess), + WorkerThreadSemaphore::Delegate( + &static_cast(outer.get())->semaphore_, + join_called_for_testing) {} + +void ThreadGroupSemaphore::SemaphoreWorkerDelegate::OnMainEntry( + WorkerThread* worker) { + OnMainEntryImpl(worker); +} + +void ThreadGroupSemaphore::SemaphoreWorkerDelegate::OnMainExit( + WorkerThread* worker_base) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + +#if DCHECK_IS_ON() + WorkerThreadSemaphore* worker = + static_cast(worker_base); + { + bool shutdown_complete = outer()->task_tracker_->IsShutdownComplete(); + CheckedAutoLock auto_lock(outer()->lock_); + + // `worker` should already have been removed from `workers_` by the time the + // thread is about to exit. (except in the cases where the thread group is + // no longer going to be used - in which case, it's fine for there to be + // invalid workers in the thread group). + if (!shutdown_complete && !outer()->join_called_for_testing_.IsSet()) { + DCHECK(!ContainsWorker(outer()->workers_, worker)); + } + } +#endif + +#if BUILDFLAG(IS_WIN) + worker_only().win_thread_environment.reset(); +#endif // BUILDFLAG(IS_WIN) + + // Count cleaned up workers for tests. It's important to do this here + // instead of at the end of CleanupLockRequired() because some side-effects + // of cleaning up happen outside the lock (e.g. recording histograms) and + // resuming from tests must happen-after that point or checks on the main + // thread will be flaky (crbug.com/1047733). + CheckedAutoLock auto_lock(outer()->lock_); + ++outer()->num_workers_cleaned_up_for_testing_; +#if DCHECK_IS_ON() + outer()->some_workers_cleaned_up_for_testing_ = true; +#endif + if (outer()->num_workers_cleaned_up_for_testing_cv_) { + outer()->num_workers_cleaned_up_for_testing_cv_->Signal(); + } +} + +bool ThreadGroupSemaphore::SemaphoreWorkerDelegate::CanGetWorkLockRequired( + BaseScopedCommandsExecutor* executor, + WorkerThread* worker_base) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + WorkerThreadSemaphore* worker = + static_cast(worker_base); + + AnnotateAcquiredLockAlias annotate(outer()->lock_, lock()); + // `timed_out_` is set by TimedWait(). + if (timed_out_) { + if (CanCleanupLockRequired(worker)) { + CleanupLockRequired(executor, worker); + } + return false; + } + + // If too many workers are currently awake (contrasted with ThreadGroupImpl + // where this decision is made by the number of workers which were signaled), + // this worker should not get work, until tasks are no longer in excess + // (i.e. max tasks increases). + if (static_cast(outer()->num_active_signals_) > outer()->max_tasks_) { + OnWorkerBecomesIdleLockRequired(executor, worker); + return false; + } + return true; +} + +RegisteredTaskSource ThreadGroupSemaphore::SemaphoreWorkerDelegate::GetWork( + WorkerThread* worker) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + DCHECK(!read_worker().current_task_priority); + DCHECK(!read_worker().current_shutdown_behavior); + + SemaphoreScopedCommandsExecutor executor(outer()); + CheckedAutoLock auto_lock(outer()->lock_); + AnnotateAcquiredLockAlias alias( + outer()->lock_, static_cast(outer_.get())->lock_); + + return GetWorkLockRequired(&executor, worker); +} + +RegisteredTaskSource +ThreadGroupSemaphore::SemaphoreWorkerDelegate::SwapProcessedTask( + RegisteredTaskSource task_source, + WorkerThread* worker) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + DCHECK(read_worker().current_task_priority); + DCHECK(read_worker().current_shutdown_behavior); + + // A transaction to the TaskSource to reenqueue, if any. Instantiated here as + // `TaskSource::lock_` is a UniversalPredecessor and must always be acquired + // prior to acquiring a second lock + absl::optional + transaction_with_task_source; + if (task_source) { + transaction_with_task_source.emplace( + RegisteredTaskSourceAndTransaction::FromTaskSource( + std::move(task_source))); + } + + SemaphoreScopedCommandsExecutor workers_executor(outer()); + ScopedReenqueueExecutor reenqueue_executor; + CheckedAutoLock auto_lock(outer()->lock_); + AnnotateAcquiredLockAlias annotate(outer()->lock_, lock()); + + // During shutdown, max_tasks may have been incremented in + // OnShutdownStartedLockRequired(). + if (incremented_max_tasks_for_shutdown_) { + DCHECK(outer()->shutdown_started_); + outer()->DecrementMaxTasksLockRequired(); + if (*read_worker().current_task_priority == TaskPriority::BEST_EFFORT) { + outer()->DecrementMaxBestEffortTasksLockRequired(); + } + incremented_max_tasks_since_blocked_ = false; + incremented_max_best_effort_tasks_since_blocked_ = false; + incremented_max_tasks_for_shutdown_ = false; + } + + DCHECK(read_worker().blocking_start_time.is_null()); + DCHECK(!incremented_max_tasks_since_blocked_); + DCHECK(!incremented_max_best_effort_tasks_since_blocked_); + + // Running task bookkeeping. + outer()->DecrementTasksRunningLockRequired( + *read_worker().current_task_priority); + write_worker().current_shutdown_behavior = absl::nullopt; + write_worker().current_task_priority = absl::nullopt; + + if (transaction_with_task_source) { + // If there is a task to enqueue, we can swap it for another task without + // changing DesiredNumAwakeWorkers(), and thus without worrying about + // signaling/waiting. + outer()->ReEnqueueTaskSourceLockRequired( + &workers_executor, &reenqueue_executor, + std::move(transaction_with_task_source.value())); + + return GetWorkLockRequired(&workers_executor, + static_cast(worker)); + } else if (outer()->GetDesiredNumAwakeWorkersLockRequired() >= + static_cast(outer()->num_active_signals_)) { + // When the thread pool wants more work to be run but hasn't signaled + // workers for it yet we can take advantage and grab more work without + // signal/wait contention. + return GetWorkLockRequired(&workers_executor, + static_cast(worker)); + } + + // In the case where the worker does not have a task source to exchange and + // the thread group doesn't want more work than the number of workers awake, + // it must WaitForWork(), to keep `num_active_signals` synchronized with the + // number of desired awake workers. + OnWorkerBecomesIdleLockRequired(&workers_executor, worker); + return nullptr; +} + +TimeDelta ThreadGroupSemaphore::SemaphoreWorkerDelegate::GetSleepTimeout() { + return ThreadPoolSleepTimeout(); +} + +bool ThreadGroupSemaphore::SemaphoreWorkerDelegate::CanCleanupLockRequired( + const WorkerThread* worker) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + return is_excess_ && LIKELY(!outer()->worker_cleanup_disallowed_for_testing_); +} + +void ThreadGroupSemaphore::SemaphoreWorkerDelegate::CleanupLockRequired( + BaseScopedCommandsExecutor* executor, + WorkerThread* worker_base) { + WorkerThreadSemaphore* worker = + static_cast(worker_base); + DCHECK(!outer()->join_called_for_testing_.IsSet()); + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + + worker->Cleanup(); + + // Remove the worker from `workers_`. + DCHECK(!outer()->after_start().no_worker_reclaim || + outer()->workers_.size() > outer()->after_start().initial_max_tasks); + auto num_erased = std::erase(outer()->workers_, worker); + CHECK_EQ(num_erased, 1u); +} + +void ThreadGroupSemaphore::SemaphoreWorkerDelegate:: + OnWorkerBecomesIdleLockRequired(BaseScopedCommandsExecutor* executor, + WorkerThread* worker_base) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + --outer()->num_active_signals_; + outer()->idle_workers_set_cv_for_testing_->Signal(); + CHECK_GE(outer()->num_active_signals_, 0); +} + +void ThreadGroupSemaphore::SemaphoreWorkerDelegate::RecordUnnecessaryWakeup() { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + RecordUnnecessaryWakeupImpl(); +} + +void ThreadGroupSemaphore::JoinForTesting() { + decltype(workers_) workers_copy; + { + SemaphoreScopedCommandsExecutor executor(this); + CheckedAutoLock auto_lock(lock_); + AnnotateAcquiredLockAlias alias(lock_, executor.outer()->lock_); + priority_queue_.EnableFlushTaskSourcesOnDestroyForTesting(); + + DCHECK_GT(workers_.size(), size_t(0)) + << "Joined an unstarted thread group."; + + join_called_for_testing_.Set(); + + // Ensure WorkerThreads in `workers_` do not attempt to cleanup while + // being joined. + worker_cleanup_disallowed_for_testing_ = true; + + // Make a copy of the WorkerThreads so that we can call + // WorkerThread::JoinForTesting() without holding `lock_` since + // WorkerThreads may need to access `workers_`. + workers_copy = workers_; + + for (size_t i = 0; i < workers_copy.size(); ++i) { + executor.ScheduleSignal(); + } + join_called_for_testing_.Set(); + } + for (const auto& worker : workers_copy) { + static_cast(worker.get())->JoinForTesting(); + } + + CheckedAutoLock auto_lock(lock_); + DCHECK(workers_ == workers_copy); + // Release `workers_` to clear their TrackedRef against `this`. + workers_.clear(); +} + +void ThreadGroupSemaphore::CreateAndRegisterWorkerLockRequired( + SemaphoreScopedCommandsExecutor* executor) { + if (workers_.size() == kMaxNumberOfWorkers) { + return; + } + DCHECK_LT(workers_.size(), kMaxNumberOfWorkers); + if (workers_.size() >= max_tasks_) { + return; + } + DCHECK(!join_called_for_testing_.IsSet()); + + // WorkerThread needs `lock_` as a predecessor for its thread lock because in + // GetWork(), `lock_` is first acquired and then the thread lock is acquired + // when GetLastUsedTime() is called on the worker by CanGetWorkLockRequired(). + scoped_refptr worker = + MakeRefCounted( + thread_type_hint_, + std::make_unique( + tracked_ref_factory_.GetTrackedRef(), + /*is_excess=*/after_start().no_worker_reclaim + ? workers_.size() >= after_start().initial_max_tasks + : true, + &join_called_for_testing_), + task_tracker_, worker_sequence_num_++, &lock_, &semaphore_); + DCHECK(worker); + workers_.push_back(worker); + DCHECK_LE(workers_.size(), max_tasks_); + executor->ScheduleStart(worker); +} + +void ThreadGroupSemaphore::DidUpdateCanRunPolicy() { + SemaphoreScopedCommandsExecutor executor(this); + CheckedAutoLock auto_lock(lock_); + EnsureEnoughWorkersLockRequired(&executor); +} + +ThreadGroup::ThreadGroupWorkerDelegate* ThreadGroupSemaphore::GetWorkerDelegate( + WorkerThread* worker) { + return static_cast( + static_cast(worker->delegate())); +} + +void ThreadGroupSemaphore::OnShutdownStarted() { + SemaphoreScopedCommandsExecutor executor(this); + OnShutDownStartedImpl(&executor); +} + +void ThreadGroupSemaphore::EnsureEnoughWorkersLockRequired( + BaseScopedCommandsExecutor* base_executor) { + // Don't do anything if the thread group isn't started. + if (max_tasks_ == 0 || UNLIKELY(join_called_for_testing_.IsSet())) { + return; + } + + SemaphoreScopedCommandsExecutor* executor = + static_cast(base_executor); + + const size_t desired_awake_workers = GetDesiredNumAwakeWorkersLockRequired(); + // The +1 here is due to the fact that we always want there to be one idle + // worker. + const size_t num_workers_to_create = + std::min({static_cast(after_start().max_num_workers_created), + static_cast( + ClampSub(desired_awake_workers + 1, workers_.size()))}); + for (size_t i = 0; i < num_workers_to_create; ++i) { + CreateAndRegisterWorkerLockRequired(executor); + } + + const size_t new_signals = std::min( + // Don't signal more than `workers_.size()` workers. + {static_cast(ClampSub(workers_.size(), num_active_signals_)), + static_cast( + ClampSub(desired_awake_workers, num_active_signals_))}); + AnnotateAcquiredLockAlias alias(lock_, executor->outer()->lock_); + for (size_t i = 0; i < new_signals; ++i) { + executor->ScheduleSignal(); + } + + // This function is called every time a task source is (re-)enqueued, + // hence the minimum priority needs to be updated. + UpdateMinAllowedPriorityLockRequired(); + + // Ensure that the number of workers is periodically adjusted if needed. + MaybeScheduleAdjustMaxTasksLockRequired(executor); +} + +} // namespace internal +} // namespace base diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.h b/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.h new file mode 100644 index 0000000000..3fb5bab92f --- /dev/null +++ b/naiveproxy/src/base/task/thread_pool/thread_group_semaphore.h @@ -0,0 +1,114 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_SEMAPHORE_H_ +#define BASE_TASK_THREAD_POOL_THREAD_GROUP_SEMAPHORE_H_ + +#include "base/base_export.h" +#include "base/strings/string_piece.h" +#include "base/task/thread_pool/task_source.h" +#include "base/task/thread_pool/thread_group_impl.h" +#include "base/task/thread_pool/worker_thread_semaphore.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace base { + +class WorkerThreadObserver; + +namespace internal { + +class TaskTracker; + +// A group of `WorkerThreadSemaphore`s that run `Task`s. +class BASE_EXPORT ThreadGroupSemaphore : public ThreadGroup { + public: + // Constructs a group without workers. + // + // `histogram_label` is used to label the thread group's histograms as + // "ThreadPool." + histogram_name + "." + `histogram_label` + extra suffixes. + // It must not be empty. `thread_group_label` is used to label the thread + // group's threads, it must not be empty. `thread_type_hint` is the preferred + // thread type; the actual thread type depends on shutdown state and platform + // capabilities. `task_tracker` keeps track of tasks. + ThreadGroupSemaphore(StringPiece histogram_label, + StringPiece thread_group_label, + ThreadType thread_type_hint, + TrackedRef task_tracker, + TrackedRef delegate); + + ThreadGroupSemaphore(const ThreadGroupSemaphore&) = delete; + ThreadGroupSemaphore& operator=(const ThreadGroupSemaphore&) = delete; + // Destroying a ThreadGroupSemaphore returned by Create() is not allowed + // in production; it is always leaked. In tests, it can only be destroyed + // after JoinForTesting() has returned. + ~ThreadGroupSemaphore() override; + + // ThreadGroup: + void Start(size_t max_tasks, + size_t max_best_effort_tasks, + TimeDelta suggested_reclaim_time, + scoped_refptr service_thread_task_runner, + WorkerThreadObserver* worker_thread_observer, + WorkerEnvironment worker_environment, + bool synchronous_thread_start_for_testing = false, + absl::optional may_block_threshold = + absl::optional()) override; + void JoinForTesting() override; + void DidUpdateCanRunPolicy() override; + void OnShutdownStarted() override; + std::unique_ptr GetExecutor() override; + size_t NumberOfIdleWorkersLockRequiredForTesting() const + EXCLUSIVE_LOCKS_REQUIRED(lock_) override; + + private: + class SemaphoreScopedCommandsExecutor; + class SemaphoreWorkerDelegate; + + // friend tests so that they can access `blocked_workers_poll_period` and + // may_block_threshold(), both in ThreadGroup. + friend class ThreadGroupSemaphoreBlockingTest; + friend class ThreadGroupSemaphoreMayBlockTest; + FRIEND_TEST_ALL_PREFIXES(ThreadGroupSemaphoreBlockingTest, + ThreadBlockUnblockPremature); + FRIEND_TEST_ALL_PREFIXES(ThreadGroupSemaphoreBlockingTest, + ThreadBlockUnblockPrematureBestEffort); + + // ThreadGroup: + void UpdateSortKey(TaskSource::Transaction transaction) override; + void PushTaskSourceAndWakeUpWorkers( + RegisteredTaskSourceAndTransaction transaction_with_task_source) override; + void EnsureEnoughWorkersLockRequired(BaseScopedCommandsExecutor* executor) + override EXCLUSIVE_LOCKS_REQUIRED(lock_); + ThreadGroupWorkerDelegate* GetWorkerDelegate(WorkerThread* worker) override; + + void CreateAndRegisterWorkerLockRequired( + SemaphoreScopedCommandsExecutor* executor) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + + // Passed to SemaphoreWorkerDelegate. + Semaphore semaphore_{0}; + AtomicFlag join_called_for_testing_{}; + + // A worker (any worker) becomes 'signaled' when the semaphore is incremented, + // and is no longer considered signaled at + // OnWorkerBecomesIdleLockRequired(). Will not exceed `workers_.size()` due to + // being deliberately capped in`EnsureEnoughWorkersLockRequired(). + int num_active_signals_ GUARDED_BY(lock_) = 0; + + size_t worker_sequence_num_ GUARDED_BY(lock_) = 0; + + // Ensures recently cleaned up workers (ref. + // SemaphoreWorkerDelegate::CleanupLockRequired()) had time to exit as + // they have a raw reference to `this` (and to TaskTracker) which can + // otherwise result in racy use-after-frees per no longer being part of + // `workers_` and hence not being explicitly joined in JoinForTesting(): + // https://crbug.com/810464. Uses AtomicRefCount to make its only public + // method thread-safe. + TrackedRefFactory tracked_ref_factory_; +}; + +} // namespace internal +} // namespace base + +#endif // BASE_TASK_THREAD_POOL_THREAD_GROUP_SEMAPHORE_H_ diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.cc b/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.cc index b09e7a3f5f..a9afd71c9e 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.cc @@ -4,6 +4,8 @@ #include "base/task/thread_pool/thread_group_worker_delegate.h" +#include "base/metrics/histogram_functions.h" +#include "base/strings/stringprintf.h" #include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call_internal.h" #include "base/threading/thread_checker.h" @@ -13,8 +15,9 @@ namespace base::internal { ThreadGroup::ThreadGroupWorkerDelegate::ThreadGroupWorkerDelegate( - TrackedRef outer) - : outer_(outer) { + TrackedRef outer, + bool is_excess) + : outer_(outer), is_excess_(is_excess) { // Bound in OnMainEntry(). DETACH_FROM_THREAD(worker_thread_checker_); } @@ -26,7 +29,7 @@ ThreadGroup::ThreadGroupWorkerDelegate::WorkerOnly::~WorkerOnly() = default; TimeDelta ThreadGroup::ThreadGroupWorkerDelegate::ThreadPoolSleepTimeout() { DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); - if (!IsExcess()) { + if (!is_excess_) { return TimeDelta::Max(); } // Sleep for an extra 10% to avoid the following pathological case: @@ -217,4 +220,98 @@ void ThreadGroup::ThreadGroupWorkerDelegate::IncrementMaxTasksLockRequired() } } +RegisteredTaskSource +ThreadGroup::ThreadGroupWorkerDelegate::GetWorkLockRequired( + BaseScopedCommandsExecutor* executor, + WorkerThread* worker) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + DCHECK(ContainsWorker(outer_->workers_, worker)); + + // Use this opportunity, before assigning work to this worker, to + // create/signal additional workers if needed (doing this here allows us to + // reduce potentially expensive create/wake directly on PostTask()). + // + // Note: FlushWorkerCreation() below releases |outer_->lock_|. It is thus + // important that all other operations come after it to keep this method + // transactional. + outer_->EnsureEnoughWorkersLockRequired(executor); + executor->FlushWorkerCreation(&outer_->lock_); + + if (!CanGetWorkLockRequired(executor, worker)) { + return nullptr; + } + + RegisteredTaskSource task_source; + TaskPriority priority; + while (!task_source && !outer_->priority_queue_.IsEmpty()) { + // Enforce the CanRunPolicy and that no more than |max_best_effort_tasks_| + // BEST_EFFORT tasks run concurrently. + priority = outer_->priority_queue_.PeekSortKey().priority(); + if (!outer_->task_tracker_->CanRunPriority(priority) || + (priority == TaskPriority::BEST_EFFORT && + outer_->num_running_best_effort_tasks_ >= + outer_->max_best_effort_tasks_)) { + break; + } + + task_source = outer_->TakeRegisteredTaskSource(executor); + } + if (!task_source) { + OnWorkerBecomesIdleLockRequired(executor, worker); + return nullptr; + } + + // Running task bookkeeping. + outer_->IncrementTasksRunningLockRequired(priority); + + write_worker().current_task_priority = priority; + write_worker().current_shutdown_behavior = task_source->shutdown_behavior(); + + return task_source; +} + +void ThreadGroup::ThreadGroupWorkerDelegate::RecordUnnecessaryWakeupImpl() { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + + base::BooleanHistogram::FactoryGet( + std::string("ThreadPool.UnnecessaryWakeup.") + outer_->histogram_label_, + base::Histogram::kUmaTargetedHistogramFlag) + ->Add(true); + + TRACE_EVENT_INSTANT("wakeup.flow", "ThreadPool.UnnecessaryWakeup"); +} + +void ThreadGroup::ThreadGroupWorkerDelegate::OnMainEntryImpl( + WorkerThread* worker) { + DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_); + + { +#if DCHECK_IS_ON() + CheckedAutoLock auto_lock(outer_->lock_); + DCHECK( + ContainsWorker(outer_->workers_, static_cast(worker))); +#endif + } + +#if BUILDFLAG(IS_WIN) + worker_only().win_thread_environment = GetScopedWindowsThreadEnvironment( + outer_->after_start().worker_environment); +#endif // BUILDFLAG(IS_WIN) + + PlatformThread::SetName( + StringPrintf("ThreadPool%sWorker", outer_->thread_group_label_.c_str())); + + outer_->BindToCurrentThread(); + worker_only().worker_thread_ = static_cast(worker); + SetBlockingObserverForCurrentThread(this); + + if (outer_->worker_started_for_testing_) { + // When |worker_started_for_testing_| is set, the thread that starts workers + // should wait for a worker to have started before starting the next one, + // and there should only be one thread that wakes up workers at a time. + DCHECK(!outer_->worker_started_for_testing_->IsSignaled()); + outer_->worker_started_for_testing_->Signal(); + } +} + } // namespace base::internal diff --git a/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.h b/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.h index c83ec31048..64df487cf9 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.h +++ b/naiveproxy/src/base/task/thread_pool/thread_group_worker_delegate.h @@ -21,7 +21,8 @@ namespace base::internal { // ThreadGroup. class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver { public: - explicit ThreadGroupWorkerDelegate(TrackedRef outer); + explicit ThreadGroupWorkerDelegate(TrackedRef outer, + bool is_excess); ThreadGroupWorkerDelegate(const ThreadGroupWorkerDelegate&) = delete; ThreadGroupWorkerDelegate& operator=(const ThreadGroupWorkerDelegate&) = delete; @@ -53,9 +54,6 @@ class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver { return *read_any().current_task_priority; } - // True if the calling worker is be eligible for reclaim. - virtual bool IsExcess() const = 0; - // Exposed for AnnotateAcquiredLockAlias. const CheckedLock& lock() const LOCK_RETURNED(outer_->lock_) { return outer_->lock_; @@ -73,6 +71,10 @@ class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver { WorkerThread* worker) EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0; + RegisteredTaskSource GetWorkLockRequired(BaseScopedCommandsExecutor* executor, + WorkerThread* worker) + EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_); + // Calls cleanup on |worker| and removes it from the thread group. Called from // GetWork() when no work is available and CanCleanupLockRequired() returns // true. @@ -85,6 +87,10 @@ class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver { BaseScopedCommandsExecutor* executor, WorkerThread* worker) EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0; + // See worker_thread.h for documentation. + void OnMainEntryImpl(WorkerThread* worker); + void RecordUnnecessaryWakeupImpl(); + // Only used in DCHECKs. template bool ContainsWorker(const std::vector>& workers, @@ -147,6 +153,11 @@ class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver { const TrackedRef outer_; + // Whether the worker is in excess. This must be decided at worker creation + // time to prevent unnecessarily discarding TLS state, as well as any behavior + // the OS has learned about a given thread. + const bool is_excess_; + // Whether |outer_->max_tasks_|/|outer_->max_best_effort_tasks_| were // incremented due to a ScopedBlockingCall on the thread. bool incremented_max_tasks_since_blocked_ GUARDED_BY(outer_->lock_) = false; diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc index 9606312d32..a13882c418 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.cc @@ -11,7 +11,6 @@ #include "base/base_switches.h" #include "base/command_line.h" #include "base/compiler_specific.h" -#include "base/debug/alias.h" #include "base/debug/leak_annotations.h" #include "base/feature_list.h" #include "base/functional/bind.h" @@ -28,6 +27,7 @@ #include "base/task/thread_pool/task_source.h" #include "base/task/thread_pool/task_source_sort_key.h" #include "base/task/thread_pool/thread_group_impl.h" +#include "base/task/thread_pool/thread_group_semaphore.h" #include "base/task/thread_pool/worker_thread.h" #include "base/thread_annotations.h" #include "base/threading/platform_thread.h" @@ -76,6 +76,7 @@ ThreadPoolImpl::ThreadPoolImpl(StringPiece histogram_label, bool use_background_threads) : histogram_label_(histogram_label), task_tracker_(std::move(task_tracker)), + use_background_threads_(use_background_threads), single_thread_task_runner_manager_(task_tracker_->GetTrackedRef(), &delayed_task_manager_), has_disable_best_effort_switch_(HasDisableBestEffortTasksSwitch()), @@ -140,20 +141,72 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params, if (g_synchronous_thread_start_for_testing) service_thread_.WaitUntilThreadStarted(); - if (FeatureList::IsEnabled(kUseUtilityThreadGroup) && - CanUseUtilityThreadTypeForWorkerThread()) { - utility_thread_group_ = std::make_unique( + if (FeatureList::IsEnabled(kThreadGroupSemaphore)) { + auto old_foreground_group = std::move(foreground_thread_group_); + + foreground_thread_group_ = std::make_unique( histogram_label_.empty() ? std::string() - : JoinString( - {histogram_label_, kUtilityPoolEnvironmentParams.name_suffix}, - "."), - kUtilityPoolEnvironmentParams.name_suffix, - kUtilityPoolEnvironmentParams.thread_type_hint, + : JoinString({histogram_label_, + kForegroundPoolEnvironmentParams.name_suffix}, + "."), + kForegroundPoolEnvironmentParams.name_suffix, + kForegroundPoolEnvironmentParams.thread_type_hint, task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef()); - foreground_thread_group_ - ->HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( - utility_thread_group_.get()); + + old_foreground_group->HandoffAllTaskSourcesToOtherThreadGroup( + foreground_thread_group_.get()); + + if (background_thread_group_) { + auto old_background_group = std::move(background_thread_group_); + + background_thread_group_ = std::make_unique( + histogram_label_.empty() + ? std::string() + : JoinString({histogram_label_, + kBackgroundPoolEnvironmentParams.name_suffix}, + "."), + kBackgroundPoolEnvironmentParams.name_suffix, + use_background_threads_ + ? kBackgroundPoolEnvironmentParams.thread_type_hint + : kForegroundPoolEnvironmentParams.thread_type_hint, + task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef()); + + old_background_group->HandoffAllTaskSourcesToOtherThreadGroup( + background_thread_group_.get()); + } + + if (FeatureList::IsEnabled(kUseUtilityThreadGroup) && + CanUseUtilityThreadTypeForWorkerThread()) { + utility_thread_group_ = std::make_unique( + histogram_label_.empty() + ? std::string() + : JoinString({histogram_label_, + kUtilityPoolEnvironmentParams.name_suffix}, + "."), + kUtilityPoolEnvironmentParams.name_suffix, + kUtilityPoolEnvironmentParams.thread_type_hint, + task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef()); + foreground_thread_group_ + ->HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( + utility_thread_group_.get()); + } + } else { + if (FeatureList::IsEnabled(kUseUtilityThreadGroup) && + CanUseUtilityThreadTypeForWorkerThread()) { + utility_thread_group_ = std::make_unique( + histogram_label_.empty() + ? std::string() + : JoinString({histogram_label_, + kUtilityPoolEnvironmentParams.name_suffix}, + "."), + kUtilityPoolEnvironmentParams.name_suffix, + kUtilityPoolEnvironmentParams.thread_type_hint, + task_tracker_->GetTrackedRef(), tracked_ref_factory_.GetTrackedRef()); + foreground_thread_group_ + ->HandoffNonUserBlockingTaskSourcesToOtherThreadGroup( + utility_thread_group_.get()); + } } // Update the CanRunPolicy based on |has_disable_best_effort_switch_|. @@ -186,26 +239,26 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params, // tasks that can run in foreground pools to ensure that there is always // room for incoming foreground tasks and to minimize the performance impact // of best-effort tasks. - static_cast(foreground_thread_group_.get()) - ->Start(foreground_threads, max_best_effort_tasks, - init_params.suggested_reclaim_time, service_thread_task_runner, - worker_thread_observer, worker_environment, - g_synchronous_thread_start_for_testing); + foreground_thread_group_.get()->Start( + foreground_threads, max_best_effort_tasks, + init_params.suggested_reclaim_time, service_thread_task_runner, + worker_thread_observer, worker_environment, + g_synchronous_thread_start_for_testing); if (utility_thread_group_) { - static_cast(utility_thread_group_.get()) - ->Start(utility_threads, max_best_effort_tasks, - init_params.suggested_reclaim_time, service_thread_task_runner, - worker_thread_observer, worker_environment, - g_synchronous_thread_start_for_testing); + utility_thread_group_.get()->Start( + utility_threads, max_best_effort_tasks, + init_params.suggested_reclaim_time, service_thread_task_runner, + worker_thread_observer, worker_environment, + g_synchronous_thread_start_for_testing); } if (background_thread_group_) { - static_cast(background_thread_group_.get()) - ->Start(max_best_effort_tasks, max_best_effort_tasks, - init_params.suggested_reclaim_time, service_thread_task_runner, - worker_thread_observer, worker_environment, - g_synchronous_thread_start_for_testing); + background_thread_group_.get()->Start( + max_best_effort_tasks, max_best_effort_tasks, + init_params.suggested_reclaim_time, service_thread_task_runner, + worker_thread_observer, worker_environment, + g_synchronous_thread_start_for_testing); } started_ = true; @@ -417,15 +470,6 @@ bool ThreadPoolImpl::PostTaskWithSequence(Task task, CHECK(task.task); DCHECK(sequence); -#if BUILDFLAG(IS_WIN) - // Force reading |task.posted_from.file_name()| to produce a useful crash - // report if the address is invalid. A crash report generated later when the - // task is executed would not contain the PostTask stack. - // - // TODO(crbug.com/1224432): Remove after resolving the crash. - DEBUG_ALIAS_FOR_CSTR(task_posted_from, task.posted_from.file_name(), 32); -#endif - if (!task_tracker_->WillPostTask(&task, sequence->shutdown_behavior())) { // `task`'s destructor may run sequence-affine code, so it must be leaked // when `WillPostTask` returns false. diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.h b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.h index 3837267a60..936509911a 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_impl.h +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_impl.h @@ -174,6 +174,7 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance, const std::string histogram_label_; const std::unique_ptr task_tracker_; + const bool use_background_threads_; ServiceThread service_thread_; DelayedTaskManager delayed_task_manager_; PooledSingleThreadTaskRunnerManager single_thread_task_runner_manager_; diff --git a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h index a4f78b39c4..1fd429d570 100644 --- a/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h +++ b/naiveproxy/src/base/task/thread_pool/thread_pool_instance.h @@ -63,7 +63,9 @@ class BASE_EXPORT ThreadPoolInstance { ~InitParams(); // Maximum number of unblocked tasks that can run concurrently in the - // foreground thread group. + // foreground thread group. This is capped at 256 (and should likely not be + // configured anywhere close to this in a browser, approaching that limit is + // most useful on compute farms running tests or compiles in parallel). size_t max_num_foreground_threads; // Maximum number of unblocked tasks that can run concurrently in the diff --git a/naiveproxy/src/base/task/thread_pool/tracked_ref.h b/naiveproxy/src/base/task/thread_pool/tracked_ref.h index 502bdc9c10..c799b98dc7 100644 --- a/naiveproxy/src/base/task/thread_pool/tracked_ref.h +++ b/naiveproxy/src/base/task/thread_pool/tracked_ref.h @@ -119,8 +119,8 @@ class TrackedRef { factory_->live_tracked_refs_.Increment(); } - raw_ptr ptr_; - raw_ptr> factory_; + raw_ptr ptr_; + raw_ptr, LeakedDanglingUntriaged> factory_; }; // TrackedRefFactory should be the last member of T. diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread.cc b/naiveproxy/src/base/task/thread_pool/worker_thread.cc index 9e31c1bcb2..3d11270465 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread.cc +++ b/naiveproxy/src/base/task/thread_pool/worker_thread.cc @@ -138,12 +138,16 @@ TimeDelta WorkerThread::Delegate::GetSleepTimeBeforePurge( WorkerThread::WorkerThread(ThreadType thread_type_hint, TrackedRef task_tracker, size_t sequence_num, - const CheckedLock* predecessor_lock) + const CheckedLock* predecessor_lock, + void* flow_terminator) : thread_lock_(predecessor_lock), task_tracker_(std::move(task_tracker)), thread_type_hint_(thread_type_hint), current_thread_type_(GetDesiredThreadType()), - sequence_num_(sequence_num) { + sequence_num_(sequence_num), + flow_terminator_(flow_terminator == nullptr + ? reinterpret_cast(this) + : reinterpret_cast(flow_terminator)) { DCHECK(task_tracker_); DCHECK(CanUseBackgroundThreadTypeForWorkerThread() || thread_type_hint_ != ThreadType::kBackground); @@ -204,7 +208,6 @@ void WorkerThread::Destroy() { // If |thread_handle_| wasn't joined, detach it. if (!thread_handle_.is_null()) { - DCHECK(!join_called_for_testing()); PlatformThread::Detach(thread_handle_); } } @@ -399,7 +402,8 @@ void WorkerThread::RunWorker() { hang_watch_scope.reset(); delegate()->WaitForWork(); TRACE_EVENT_BEGIN("base", "WorkerThread active", - perfetto::TerminatingFlow::FromPointer(this)); + perfetto::TerminatingFlow::FromPointer( + reinterpret_cast(flow_terminator_))); // Don't GetWork() in the case where we woke up for Cleanup(). if (ShouldExit()) { diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread.h b/naiveproxy/src/base/task/thread_pool/worker_thread.h index 575e66b7d7..27817152ce 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread.h +++ b/naiveproxy/src/base/task/thread_pool/worker_thread.h @@ -127,7 +127,8 @@ class BASE_EXPORT WorkerThread : public RefCountedThreadSafe, WorkerThread(ThreadType thread_type_hint, TrackedRef task_tracker, size_t sequence_num, - const CheckedLock* predecessor_lock = nullptr); + const CheckedLock* predecessor_lock = nullptr, + void* flow_terminator = nullptr); WorkerThread(const WorkerThread&) = delete; WorkerThread& operator=(const WorkerThread&) = delete; @@ -255,6 +256,9 @@ class BASE_EXPORT WorkerThread : public RefCountedThreadSafe, const size_t sequence_num_; + // Used to terminate WorkerThread::WakeUp trace event flows. + const intptr_t flow_terminator_; + // Service thread task runner. scoped_refptr io_thread_task_runner_; }; diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.cc b/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.cc index d1d12c4cb8..545de049d3 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.cc +++ b/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.cc @@ -31,11 +31,13 @@ WorkerThreadSemaphore::WorkerThreadSemaphore( std::unique_ptr delegate, TrackedRef task_tracker, size_t sequence_num, - const CheckedLock* predecessor_lock) + const CheckedLock* predecessor_lock, + void* flow_terminator) : WorkerThread(thread_type_hint, task_tracker, sequence_num, - predecessor_lock), + predecessor_lock, + flow_terminator), delegate_(std::move(delegate)) { DCHECK(delegate_); } diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.h b/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.h index 619de24efa..e1065eac27 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.h +++ b/naiveproxy/src/base/task/thread_pool/worker_thread_semaphore.h @@ -38,7 +38,8 @@ class BASE_EXPORT WorkerThreadSemaphore : public WorkerThread { std::unique_ptr delegate, TrackedRef task_tracker, size_t sequence_num, - const CheckedLock* predecessor_lock = nullptr); + const CheckedLock* predecessor_lock = nullptr, + void* flow_terminator = nullptr); WorkerThreadSemaphore(const WorkerThread&) = delete; WorkerThreadSemaphore& operator=(const WorkerThread&) = delete; diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread_set.cc b/naiveproxy/src/base/task/thread_pool/worker_thread_set.cc index 825703b8f0..b4debad618 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread_set.cc +++ b/naiveproxy/src/base/task/thread_pool/worker_thread_set.cc @@ -55,7 +55,7 @@ void WorkerThreadSet::Remove(const WorkerThreadWaitableEvent* worker) { DCHECK(!IsEmpty()); DCHECK_NE(worker, *set_.begin()); auto it = set_.find(const_cast(worker)); - DCHECK(it != set_.end()); + CHECK(it != set_.end(), base::NotFatalUntil::M125); DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime()); set_.erase(it); } diff --git a/naiveproxy/src/base/task/thread_pool/worker_thread_set.h b/naiveproxy/src/base/task/thread_pool/worker_thread_set.h index 9137a90f1e..c98f459901 100644 --- a/naiveproxy/src/base/task/thread_pool/worker_thread_set.h +++ b/naiveproxy/src/base/task/thread_pool/worker_thread_set.h @@ -10,6 +10,7 @@ #include #include "base/base_export.h" +#include "base/memory/raw_ptr.h" namespace base { namespace internal { @@ -61,7 +62,7 @@ class BASE_EXPORT WorkerThreadSet { bool IsEmpty() const { return set_.empty(); } private: - std::set set_; + std::set, Compare> set_; }; } // namespace internal diff --git a/naiveproxy/src/base/test/BUILD.gn b/naiveproxy/src/base/test/BUILD.gn index bffe24a080..9cd7f3eaa5 100644 --- a/naiveproxy/src/base/test/BUILD.gn +++ b/naiveproxy/src/base/test/BUILD.gn @@ -103,6 +103,7 @@ static_library("test_support") { "power_monitor_test.h", "power_monitor_test_utils.cc", "power_monitor_test_utils.h", + "protobuf_matchers.cc", "protobuf_matchers.h", "rectify_callback.h", "rectify_callback_internal.h", @@ -179,6 +180,7 @@ static_library("test_support") { ] deps = [ + ":proto_test_support", "//base/third_party/dynamic_annotations", "//build:chromeos_buildflags", "//third_party/google_benchmark", @@ -640,15 +642,18 @@ if (is_android) { ] sources = [ + "android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java", "android/javatests/src/org/chromium/base/test/transit/CallbackCondition.java", "android/javatests/src/org/chromium/base/test/transit/Condition.java", "android/javatests/src/org/chromium/base/test/transit/ConditionChecker.java", "android/javatests/src/org/chromium/base/test/transit/ConditionWaiter.java", "android/javatests/src/org/chromium/base/test/transit/ConditionalState.java", + "android/javatests/src/org/chromium/base/test/transit/ElementInState.java", "android/javatests/src/org/chromium/base/test/transit/Elements.java", "android/javatests/src/org/chromium/base/test/transit/FacilityCheckIn.java", "android/javatests/src/org/chromium/base/test/transit/FacilityCheckOut.java", "android/javatests/src/org/chromium/base/test/transit/InstrumentationThreadCondition.java", + "android/javatests/src/org/chromium/base/test/transit/LogicalElement.java", "android/javatests/src/org/chromium/base/test/transit/PublicTransitConfig.java", "android/javatests/src/org/chromium/base/test/transit/StationFacility.java", "android/javatests/src/org/chromium/base/test/transit/TrafficControl.java", @@ -659,6 +664,8 @@ if (is_android) { "android/javatests/src/org/chromium/base/test/transit/Trip.java", "android/javatests/src/org/chromium/base/test/transit/UiThreadCondition.java", "android/javatests/src/org/chromium/base/test/transit/ViewConditions.java", + "android/javatests/src/org/chromium/base/test/transit/ViewElement.java", + "android/javatests/src/org/chromium/base/test/transit/ViewElementInState.java", ] } } diff --git a/naiveproxy/src/base/test/android/java_handler_thread_helpers.cc b/naiveproxy/src/base/test/android/java_handler_thread_helpers.cc index a14ff5423c..1521f7d705 100644 --- a/naiveproxy/src/base/test/android/java_handler_thread_helpers.cc +++ b/naiveproxy/src/base/test/android/java_handler_thread_helpers.cc @@ -16,14 +16,14 @@ namespace android { std::unique_ptr JavaHandlerThreadHelpers::CreateJavaFirst() { return std::make_unique( nullptr, Java_JavaHandlerThreadHelpers_testAndGetJavaHandlerThread( - base::android::AttachCurrentThread())); + jni_zero::AttachCurrentThread())); } // static void JavaHandlerThreadHelpers::ThrowExceptionAndAbort(WaitableEvent* event) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); Java_JavaHandlerThreadHelpers_throwException(env); - DCHECK(HasException(env)); + DCHECK(jni_zero::HasException(env)); base::CurrentUIThread::Get()->Abort(); event->Signal(); } @@ -31,7 +31,7 @@ void JavaHandlerThreadHelpers::ThrowExceptionAndAbort(WaitableEvent* event) { // static bool JavaHandlerThreadHelpers::IsExceptionTestException( ScopedJavaLocalRef exception) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return Java_JavaHandlerThreadHelpers_isExceptionTestException(env, exception); } diff --git a/naiveproxy/src/base/test/android/url_utils.cc b/naiveproxy/src/base/test/android/url_utils.cc index 13c09318cc..e748d2963e 100644 --- a/naiveproxy/src/base/test/android/url_utils.cc +++ b/naiveproxy/src/base/test/android/url_utils.cc @@ -12,7 +12,7 @@ namespace base { namespace android { FilePath GetIsolatedTestRoot() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); ScopedJavaLocalRef jtest_data_dir = Java_UrlUtils_getIsolatedTestRoot(env); base::FilePath test_data_dir( diff --git a/naiveproxy/src/base/test/async_results_test_values_win.h b/naiveproxy/src/base/test/async_results_test_values_win.h index 491bd767c3..8275f76d3b 100644 --- a/naiveproxy/src/base/test/async_results_test_values_win.h +++ b/naiveproxy/src/base/test/async_results_test_values_win.h @@ -19,37 +19,33 @@ namespace Foundation { template <> struct __declspec(uuid("3895C200-8F26-4F5A-B29D-2B5D72E68F99")) - ABI::Windows::Foundation::IAsyncOperation - : ABI::Windows::Foundation::IAsyncOperation_impl {}; +IAsyncOperation : IAsyncOperation_impl {}; template <> struct __declspec(uuid("CD99A253-6473-4810-AF0D-763DAB79AC42")) - ABI::Windows::Foundation::IAsyncOperationCompletedHandler - : ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl< - IUnknown*> {}; +IAsyncOperationCompletedHandler + : IAsyncOperationCompletedHandler_impl {}; template <> struct __declspec(uuid("CB52D855-8121-4AC8-A164-084A27FB377E")) - ABI::Windows::Foundation::IAsyncOperation - : ABI::Windows::Foundation::IAsyncOperation_impl {}; +IAsyncOperation : IAsyncOperation_impl {}; template <> struct __declspec(uuid("EA868415-A724-40BC-950A-C7DB6B1723C6")) - ABI::Windows::Foundation::IAsyncOperationCompletedHandler - : ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl {}; +IAsyncOperationCompletedHandler + : IAsyncOperationCompletedHandler_impl {}; // These specialization templates were included in windows.foundation.h, but // removed in 10.0.19041.0 SDK, so are included here conditionally #ifdef NTDDI_WIN10_VB // Windows 10.0.19041 template <> struct __declspec(uuid("968b9665-06ed-5774-8f53-8edeabd5f7b5")) - ABI::Windows::Foundation::IAsyncOperation - : ABI::Windows::Foundation::IAsyncOperation_impl {}; +IAsyncOperation : IAsyncOperation_impl {}; template <> struct __declspec(uuid("d60cae9d-88cb-59f1-8576-3fba44796be8")) - ABI::Windows::Foundation::IAsyncOperationCompletedHandler - : ABI::Windows::Foundation::IAsyncOperationCompletedHandler_impl {}; +IAsyncOperationCompletedHandler + : IAsyncOperationCompletedHandler_impl {}; #endif } // namespace Foundation diff --git a/naiveproxy/src/base/test/bind.h b/naiveproxy/src/base/test/bind.h index 477fd6d673..65cae13fd8 100644 --- a/naiveproxy/src/base/test/bind.h +++ b/naiveproxy/src/base/test/bind.h @@ -17,6 +17,12 @@ class Location; namespace internal { +template +static constexpr bool kHasConstCallOperator = false; +template +static constexpr bool + kHasConstCallOperator = true; + // Implementation of `BindLambdaForTesting()`, which checks preconditions before // handing off to `Bind{Once,Repeating}()`. template { private: using F = std::decay_t; - template - static constexpr bool kHasConstCallOperator = false; - template <> - static constexpr bool kHasConstCallOperator = true; - // For context on this "templated struct with a lambda that asserts" pattern, // see comments in `Invoker<>`. template && @@ -57,7 +58,8 @@ struct BindLambdaForTestingHelper { public: static auto BindLambdaForTesting(Lambda&& lambda) { - if constexpr (kHasConstCallOperator<>) { + if constexpr (kHasConstCallOperator) { // If WTF::BindRepeating is available, and a callback argument is in WTF, // then this call is ambiguous without the full namespace path. return ::base::BindRepeating(&Run, std::forward(lambda)); diff --git a/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc b/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc index 110f5a7d9e..ef87f3856f 100644 --- a/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc +++ b/naiveproxy/src/base/test/gtest_xml_unittest_result_printer.cc @@ -222,10 +222,8 @@ void XmlUnitTestResultPrinter::WriteTestPartResult( type = "skip"; break; } - std::string summary_encoded; - Base64Encode(summary, &summary_encoded); - std::string message_encoded; - Base64Encode(message, &message_encoded); + std::string summary_encoded = base::Base64Encode(summary); + std::string message_encoded = base::Base64Encode(message); fprintf(output_file_.get(), " \n" " %s\n" diff --git a/naiveproxy/src/base/test/launcher/test_results_tracker.cc b/naiveproxy/src/base/test/launcher/test_results_tracker.cc index 6306371c88..2b113168a5 100644 --- a/naiveproxy/src/base/test/launcher/test_results_tracker.cc +++ b/naiveproxy/src/base/test/launcher/test_results_tracker.cc @@ -489,8 +489,8 @@ bool TestResultsTracker::SaveSummaryAsJSON( // JSON-serialized - there are no guarantees about character encoding // of the snippet). This can be very useful piece of information when // debugging a test failure related to character encoding. - std::string base64_output_snippet; - Base64Encode(test_result.output_snippet, &base64_output_snippet); + std::string base64_output_snippet = + base::Base64Encode(test_result.output_snippet); test_result_value.Set("output_snippet_base64", base64_output_snippet); if (!test_result.links.empty()) { Value::Dict links; @@ -543,8 +543,7 @@ bool TestResultsTracker::SaveSummaryAsJSON( } result_part_value.Set("lossless_summary", lossless_summary); - std::string encoded_summary; - Base64Encode(result_part.summary, &encoded_summary); + std::string encoded_summary = base::Base64Encode(result_part.summary); result_part_value.Set("summary_base64", encoded_summary); bool lossless_message = IsStringUTF8(result_part.message); @@ -556,8 +555,7 @@ bool TestResultsTracker::SaveSummaryAsJSON( } result_part_value.Set("lossless_message", lossless_message); - std::string encoded_message; - Base64Encode(result_part.message, &encoded_message); + std::string encoded_message = base::Base64Encode(result_part.message); result_part_value.Set("message_base64", encoded_message); test_result_parts.Append(std::move(result_part_value)); diff --git a/naiveproxy/src/base/test/perf_test_suite.h b/naiveproxy/src/base/test/perf_test_suite.h index 7ae3cbf212..aa8beb000f 100644 --- a/naiveproxy/src/base/test/perf_test_suite.h +++ b/naiveproxy/src/base/test/perf_test_suite.h @@ -13,7 +13,7 @@ class PerfTestSuite : public TestSuite { public: PerfTestSuite(int argc, char** argv); - // TODO(crbug.com/1404759): Port all perf tests to Google Benchmark and + // TODO(crbug.com/40251982): Port all perf tests to Google Benchmark and // eliminate gTest dependence from perf tests. void Initialize() override; void InitializeFromCommandLine(int* argc, char** argv) override; diff --git a/naiveproxy/src/base/test/protobuf_matchers.cc b/naiveproxy/src/base/test/protobuf_matchers.cc new file mode 100644 index 0000000000..9498492ac9 --- /dev/null +++ b/naiveproxy/src/base/test/protobuf_matchers.cc @@ -0,0 +1,32 @@ +// Copyright 2024 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/files/file_path.h" +#include "base/notreached.h" +#include "base/path_service.h" +#include "base/test/test_proto_loader.h" + +namespace base::test { +namespace { + +const base::TestProtoSetLoader& EmptyMessageLoader() { + // A proto descriptor set with a single "message E{}". + const char kEmptyDescriptor[] = { + 0x0a, 0x08, 0x0a, 0x01, 0x74, 0x22, 0x03, 0x0a, 0x01, 0x45, + }; + static const base::TestProtoSetLoader loader( + std::string_view(kEmptyDescriptor, sizeof(kEmptyDescriptor))); + return loader; +} + +} // namespace + +std::string BinaryProtoToRawTextProto(const std::string& binary_message) { + // This just serializes binary_message into an empty protobuf message. All + // content is interpreted as unknown fields, and reflected in the resulting + // text format. + return EmptyMessageLoader().PrintToText("E", binary_message); +} + +} // namespace base::test diff --git a/naiveproxy/src/base/test/protobuf_matchers.h b/naiveproxy/src/base/test/protobuf_matchers.h index 192e1b1ce8..a02041e407 100644 --- a/naiveproxy/src/base/test/protobuf_matchers.h +++ b/naiveproxy/src/base/test/protobuf_matchers.h @@ -12,6 +12,10 @@ namespace base::test { +// Parses a binary proto and returns a raw TextProto, where all fields are +// unnamed. The input must be a valid serialized protobuf message. +std::string BinaryProtoToRawTextProto(const std::string& binary_message); + // Matcher that verifies two protobufs contain the same data. MATCHER_P(EqualsProto, message, @@ -28,8 +32,10 @@ MATCHER_P(EqualsProto, } if (expected_serialized != actual_serialized) { *result_listener << "Provided proto did not match the expected proto" - << "\n Serialized Expected Proto: " << expected_serialized - << "\n Serialized Provided Proto: " << actual_serialized; + << "\n Expected Raw TextProto:\n" + << BinaryProtoToRawTextProto(expected_serialized) + << "\n Provided Raw TextProto:\n" + << BinaryProtoToRawTextProto(actual_serialized); return false; } return true; diff --git a/naiveproxy/src/base/test/test_file_util_linux.cc b/naiveproxy/src/base/test/test_file_util_linux.cc index b15df061b3..2a9c7f7a8d 100644 --- a/naiveproxy/src/base/test/test_file_util_linux.cc +++ b/naiveproxy/src/base/test/test_file_util_linux.cc @@ -20,7 +20,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_file.h" -#include "base/notreached.h" +#include "base/notimplemented.h" namespace base { diff --git a/naiveproxy/src/base/test/test_file_util_posix.cc b/naiveproxy/src/base/test/test_file_util_posix.cc index f4599eb3d6..07515504c4 100644 --- a/naiveproxy/src/base/test/test_file_util_posix.cc +++ b/naiveproxy/src/base/test/test_file_util_posix.cc @@ -15,6 +15,7 @@ #include "base/check_op.h" #include "base/files/file.h" #include "base/files/file_util.h" +#include "base/notimplemented.h" #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" diff --git a/naiveproxy/src/base/test/test_pending_task.h b/naiveproxy/src/base/test/test_pending_task.h index 76312359d6..5ceb674114 100644 --- a/naiveproxy/src/base/test/test_pending_task.h +++ b/naiveproxy/src/base/test/test_pending_task.h @@ -10,10 +10,14 @@ #include "base/functional/callback.h" #include "base/location.h" #include "base/time/time.h" -#include "base/trace_event/base_tracing_forward.h" namespace base { +namespace trace_event { +class TracedValue; +class ConvertableToTraceFormat; +} // namespace trace_event + // TestPendingTask is a helper class for test TaskRunner // implementations. See test_simple_task_runner.h for example usage. diff --git a/naiveproxy/src/base/test/test_proto_loader.cc b/naiveproxy/src/base/test/test_proto_loader.cc index d57cab402b..8ee91dfd04 100644 --- a/naiveproxy/src/base/test/test_proto_loader.cc +++ b/naiveproxy/src/base/test/test_proto_loader.cc @@ -4,93 +4,106 @@ #include "base/test/test_proto_loader.h" +#include "base/check.h" #include "base/files/file_util.h" -#include "base/notreached.h" +#include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "third_party/protobuf/src/google/protobuf/descriptor.h" +#include "third_party/protobuf/src/google/protobuf/descriptor.pb.h" +#include "third_party/protobuf/src/google/protobuf/descriptor_database.h" +#include "third_party/protobuf/src/google/protobuf/dynamic_message.h" #include "third_party/protobuf/src/google/protobuf/message.h" #include "third_party/protobuf/src/google/protobuf/text_format.h" namespace base { -TestProtoLoader::TestProtoLoader(const base::FilePath& descriptor_path, - base::StringPiece type_name) { - // Load the descriptors and find the one for |type_name|. - std::string package, name; - std::vector type_name_parts = base::SplitString( - type_name, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - DCHECK_GE(type_name_parts.size(), 2U) << "|type_name| should include package"; +class TestProtoSetLoader::State { + public: + explicit State(std::string_view descriptor_binary_proto) { + CHECK(descriptor_set_.ParseFromArray(descriptor_binary_proto.data(), + descriptor_binary_proto.size())) + << "Couldn't parse descriptor"; + for (auto& file : descriptor_set_.file()) { + descriptor_database_.Add(file); + } + descriptor_pool_ = std::make_unique( + &descriptor_database_); + } - prototype_ = GetPrototype( - descriptor_path, /*package =*/ - base::JoinString( - base::make_span(type_name_parts.begin(), type_name_parts.size() - 1), - "."), - /* name = */ type_name_parts.back()); - DCHECK_NE(nullptr, prototype_); + std::unique_ptr NewMessage( + std::string_view full_type_name) { + const google::protobuf::Descriptor* message_type = + descriptor_pool_->FindMessageTypeByName(std::string(full_type_name)); + CHECK(message_type) << "Couldn't find proto message type " + << full_type_name; + return base::WrapUnique( + dynamic_message_factory_.GetPrototype(message_type)->New()); + } + + private: + google::protobuf::FileDescriptorSet descriptor_set_; + google::protobuf::SimpleDescriptorDatabase descriptor_database_; + std::unique_ptr descriptor_pool_; + google::protobuf::DynamicMessageFactory dynamic_message_factory_; +}; + +TestProtoSetLoader::TestProtoSetLoader(std::string_view descriptor_binary_proto) + : state_(std::make_unique(descriptor_binary_proto)) {} + +TestProtoSetLoader::TestProtoSetLoader(const base::FilePath& descriptor_path) { + std::string file_contents; + CHECK(base::ReadFileToString(descriptor_path, &file_contents)) + << "Couldn't load contents of " << descriptor_path; + state_ = std::make_unique(file_contents); } +TestProtoSetLoader::~TestProtoSetLoader() = default; + +std::string TestProtoSetLoader::ParseFromText( + const std::string_view type_name, + const std::string& proto_text) const { + // Create a message of the given type, parse, and return. + std::unique_ptr message = + state_->NewMessage(type_name); + CHECK( + google::protobuf::TextFormat::ParseFromString(proto_text, message.get())); + return message->SerializeAsString(); +} + +std::string TestProtoSetLoader::PrintToText( + const std::string_view type_name, + const std::string& serialized_message) const { + // Create a message of the given type, read the serialized message, and + // print to text format. + std::unique_ptr message = + state_->NewMessage(type_name); + CHECK(message->ParseFromString(serialized_message)); + std::string proto_text; + CHECK(google::protobuf::TextFormat::PrintToString(*message, &proto_text)); + return proto_text; +} + +TestProtoLoader::TestProtoLoader(std::string_view descriptor_binary_proto, + std::string_view type_name) + : set_loader_(descriptor_binary_proto), type_name_(type_name) {} + +TestProtoLoader::TestProtoLoader(const base::FilePath& descriptor_path, + std::string_view type_name) + : set_loader_(descriptor_path), type_name_(type_name) {} + TestProtoLoader::~TestProtoLoader() = default; -const google::protobuf::Message* TestProtoLoader::GetPrototype( - base::FilePath descriptor_path, - base::StringPiece package, - base::StringPiece name) { - std::string file_contents; - - if (!base::ReadFileToString(descriptor_path, &file_contents)) { - NOTREACHED() << "Couldn't load contents of " << descriptor_path; - return nullptr; - } - - if (!descriptor_set_.ParseFromString(file_contents)) { - NOTREACHED() << "Couldn't parse descriptor from " << descriptor_path; - return nullptr; - } - - for (int file_i = 0; file_i < descriptor_set_.file_size(); ++file_i) { - const google::protobuf::FileDescriptorProto& file = - descriptor_set_.file(file_i); - if (file.package() != package) { - continue; - } - const google::protobuf::FileDescriptor* descriptor = - descriptor_pool_.BuildFile(file); - for (int message_type_i = 0; - message_type_i < descriptor->message_type_count(); ++message_type_i) { - const google::protobuf::Descriptor* message_type = - descriptor->message_type(message_type_i); - if (message_type->name() != name) { - continue; - } - return dynamic_message_factory_.GetPrototype(message_type); - } - } - NOTREACHED() << "Couldn't find " << package << "." << name << "in " - << descriptor_path; - return nullptr; -} - void TestProtoLoader::ParseFromText(const std::string& proto_text, - std::string& serialized_message) { - // Parse the text using the descriptor-generated message and send it to - // |destination|. - std::unique_ptr message(prototype_->New()); - bool success = - google::protobuf::TextFormat::ParseFromString(proto_text, message.get()); - success |= message->SerializeToString(&serialized_message); - DCHECK(success); + std::string& serialized_message) const { + serialized_message = set_loader_.ParseFromText(type_name_, proto_text); } void TestProtoLoader::PrintToText(const std::string& serialized_message, - std::string& proto_text) { - // Parse the text using the descriptor-generated message and send it to - // |destination|. - std::unique_ptr message(prototype_->New()); - bool success = message->ParseFromString(serialized_message); - success |= google::protobuf::TextFormat::PrintToString(*message, &proto_text); - DCHECK(success); + std::string& proto_text) const { + proto_text = set_loader_.PrintToText(type_name_, serialized_message); } } // namespace base diff --git a/naiveproxy/src/base/test/test_proto_loader.h b/naiveproxy/src/base/test/test_proto_loader.h index 899ed71237..3cffa24ed3 100644 --- a/naiveproxy/src/base/test/test_proto_loader.h +++ b/naiveproxy/src/base/test/test_proto_loader.h @@ -5,11 +5,10 @@ #ifndef BASE_TEST_TEST_PROTO_LOADER_H_ #define BASE_TEST_TEST_PROTO_LOADER_H_ +#include +#include +#include #include "base/files/file_path.h" -#include "base/memory/raw_ptr.h" -#include "third_party/protobuf/src/google/protobuf/descriptor.h" -#include "third_party/protobuf/src/google/protobuf/descriptor.pb.h" -#include "third_party/protobuf/src/google/protobuf/dynamic_message.h" namespace base { @@ -42,26 +41,49 @@ namespace base { // This class uses the protobuf descriptors (generated at compile time) to // generate a |Message| that can be used to parse from text. This message can // then be serialized to binary which can be parsed by the |MessageLite|. +class PROTO_TEST_EXPORT TestProtoSetLoader { + public: + explicit TestProtoSetLoader(const base::FilePath& descriptor_path); + explicit TestProtoSetLoader(std::string_view descriptor_binary_proto); + ~TestProtoSetLoader(); + TestProtoSetLoader(const TestProtoSetLoader&) = delete; + TestProtoSetLoader& operator=(const TestProtoSetLoader&) = delete; + + // Parse a text proto into a binary proto. `type_name` is the full message + // type name including the package. This CHECK fails if the type is not + // found, or if the text cannot be parsed. + std::string ParseFromText(std::string_view type_name, + const std::string& proto_text) const; + + // Returns the text proto format of `message`. This CHECK fails on error. + std::string PrintToText(std::string_view type_name, + const std::string& message) const; + + private: + // Hide dependencies of protobuf_full from the header, so that + // proto_test_support doesn't need to add protobuf_full as a public dep. + class State; + + std::unique_ptr state_; +}; + +// Same as TestProtoSetLoader, but for a single message type. class PROTO_TEST_EXPORT TestProtoLoader { public: TestProtoLoader(const base::FilePath& descriptor_path, - base::StringPiece type_name); + std::string_view type_name); + TestProtoLoader(std::string_view descriptor_binary_proto, + std::string_view type_name); ~TestProtoLoader(); TestProtoLoader(const TestProtoLoader&) = delete; TestProtoLoader& operator=(const TestProtoLoader&) = delete; - void ParseFromText(const std::string& proto_text, std::string& message); - void PrintToText(const std::string& message, std::string& proto_text); + void ParseFromText(const std::string& proto_text, std::string& message) const; + void PrintToText(const std::string& message, std::string& proto_text) const; private: - const google::protobuf::Message* GetPrototype(base::FilePath descriptor_path, - base::StringPiece package, - base::StringPiece name); - - google::protobuf::DescriptorPool descriptor_pool_; - google::protobuf::FileDescriptorSet descriptor_set_; - google::protobuf::DynamicMessageFactory dynamic_message_factory_; - raw_ptr prototype_; + TestProtoSetLoader set_loader_; + std::string type_name_; }; } // namespace base diff --git a/naiveproxy/src/base/threading/hang_watcher.cc b/naiveproxy/src/base/threading/hang_watcher.cc index af5b53a6a7..3b0041d8c5 100644 --- a/naiveproxy/src/base/threading/hang_watcher.cc +++ b/naiveproxy/src/base/threading/hang_watcher.cc @@ -323,7 +323,8 @@ WatchHangsInScope::~WatchHangsInScope() { // static void HangWatcher::InitializeOnMainThread(ProcessType process_type, - bool is_zygote_child) { + bool is_zygote_child, + bool emit_crashes) { DCHECK(!g_use_hang_watcher); DCHECK(g_io_thread_log_level == LoggingLevel::kNone); DCHECK(g_main_thread_log_level == LoggingLevel::kNone); @@ -356,57 +357,57 @@ void HangWatcher::InitializeOnMainThread(ProcessType process_type, return; // Retrieve thread-specific config for hang watching. - switch (process_type) { - case HangWatcher::ProcessType::kUnknownProcess: - break; - - case HangWatcher::ProcessType::kBrowserProcess: - g_threadpool_log_level.store( - static_cast(kThreadPoolLogLevel.Get()), + if (process_type == HangWatcher::ProcessType::kBrowserProcess) { + // Crashes are set to always emit. Override any feature flags. + if (emit_crashes) { + g_io_thread_log_level.store( + static_cast(LoggingLevel::kUmaAndCrash), std::memory_order_relaxed); + g_main_thread_log_level.store( + static_cast(LoggingLevel::kUmaAndCrash), + std::memory_order_relaxed); + } else { g_io_thread_log_level.store( static_cast(kIOThreadLogLevel.Get()), std::memory_order_relaxed); g_main_thread_log_level.store( static_cast(kUIThreadLogLevel.Get()), std::memory_order_relaxed); - break; + } - case HangWatcher::ProcessType::kGPUProcess: - g_threadpool_log_level.store( - static_cast(kGPUProcessThreadPoolLogLevel.Get()), - std::memory_order_relaxed); - g_io_thread_log_level.store( - static_cast(kGPUProcessIOThreadLogLevel.Get()), - std::memory_order_relaxed); - g_main_thread_log_level.store( - static_cast(kGPUProcessMainThreadLogLevel.Get()), - std::memory_order_relaxed); - break; - - case HangWatcher::ProcessType::kRendererProcess: - g_threadpool_log_level.store( - static_cast(kRendererProcessThreadPoolLogLevel.Get()), - std::memory_order_relaxed); - g_io_thread_log_level.store( - static_cast(kRendererProcessIOThreadLogLevel.Get()), - std::memory_order_relaxed); - g_main_thread_log_level.store( - static_cast(kRendererProcessMainThreadLogLevel.Get()), - std::memory_order_relaxed); - break; - - case HangWatcher::ProcessType::kUtilityProcess: - g_threadpool_log_level.store( - static_cast(kUtilityProcessThreadPoolLogLevel.Get()), - std::memory_order_relaxed); - g_io_thread_log_level.store( - static_cast(kUtilityProcessIOThreadLogLevel.Get()), - std::memory_order_relaxed); - g_main_thread_log_level.store( - static_cast(kUtilityProcessMainThreadLogLevel.Get()), - std::memory_order_relaxed); - break; + g_threadpool_log_level.store( + static_cast(kThreadPoolLogLevel.Get()), + std::memory_order_relaxed); + } else if (process_type == HangWatcher::ProcessType::kGPUProcess) { + g_threadpool_log_level.store( + static_cast(kGPUProcessThreadPoolLogLevel.Get()), + std::memory_order_relaxed); + g_io_thread_log_level.store( + static_cast(kGPUProcessIOThreadLogLevel.Get()), + std::memory_order_relaxed); + g_main_thread_log_level.store( + static_cast(kGPUProcessMainThreadLogLevel.Get()), + std::memory_order_relaxed); + } else if (process_type == HangWatcher::ProcessType::kRendererProcess) { + g_threadpool_log_level.store( + static_cast(kRendererProcessThreadPoolLogLevel.Get()), + std::memory_order_relaxed); + g_io_thread_log_level.store( + static_cast(kRendererProcessIOThreadLogLevel.Get()), + std::memory_order_relaxed); + g_main_thread_log_level.store( + static_cast(kRendererProcessMainThreadLogLevel.Get()), + std::memory_order_relaxed); + } else if (process_type == HangWatcher::ProcessType::kUtilityProcess) { + g_threadpool_log_level.store( + static_cast(kUtilityProcessThreadPoolLogLevel.Get()), + std::memory_order_relaxed); + g_io_thread_log_level.store( + static_cast(kUtilityProcessIOThreadLogLevel.Get()), + std::memory_order_relaxed); + g_main_thread_log_level.store( + static_cast(kUtilityProcessMainThreadLogLevel.Get()), + std::memory_order_relaxed); } } @@ -1007,7 +1008,7 @@ void HangWatcher::UnregisterThread() { &std::unique_ptr::get); // Thread should be registered to get unregistered. - DCHECK(it != watch_states_.end()); + CHECK(it != watch_states_.end(), base::NotFatalUntil::M125); watch_states_.erase(it); } diff --git a/naiveproxy/src/base/threading/hang_watcher.h b/naiveproxy/src/base/threading/hang_watcher.h index 85b8e71555..f5ff23ea19 100644 --- a/naiveproxy/src/base/threading/hang_watcher.h +++ b/naiveproxy/src/base/threading/hang_watcher.h @@ -151,7 +151,8 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate { // Initializes HangWatcher. Must be called once on the main thread during // startup while single-threaded. static void InitializeOnMainThread(ProcessType process_type, - bool is_zygote_child); + bool is_zygote_child, + bool emit_crashes); // Returns the values that were set through InitializeOnMainThread() to their // default value. Used for testing since in prod initialization should happen diff --git a/naiveproxy/src/base/threading/platform_thread_internal_posix.cc b/naiveproxy/src/base/threading/platform_thread_internal_posix.cc index f589d179ca..5d8c9f8c68 100644 --- a/naiveproxy/src/base/threading/platform_thread_internal_posix.cc +++ b/naiveproxy/src/base/threading/platform_thread_internal_posix.cc @@ -11,6 +11,7 @@ #include "base/containers/adapters.h" #include "base/logging.h" +#include "base/notimplemented.h" #include "base/notreached.h" namespace base { diff --git a/naiveproxy/src/base/threading/platform_thread_posix.cc b/naiveproxy/src/base/threading/platform_thread_posix.cc index 3123adf13e..c5194f7172 100644 --- a/naiveproxy/src/base/threading/platform_thread_posix.cc +++ b/naiveproxy/src/base/threading/platform_thread_posix.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/notreached.h" #include "base/threading/platform_thread.h" #include @@ -22,6 +21,7 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" +#include "base/notimplemented.h" #include "base/threading/platform_thread_internal_posix.h" #include "base/threading/scoped_blocking_call.h" #include "base/threading/thread_id_name_manager.h" diff --git a/naiveproxy/src/base/threading/sequence_local_storage_map.cc b/naiveproxy/src/base/threading/sequence_local_storage_map.cc index b6fc41aa86..c9aa5c9c2a 100644 --- a/naiveproxy/src/base/threading/sequence_local_storage_map.cc +++ b/naiveproxy/src/base/threading/sequence_local_storage_map.cc @@ -8,6 +8,7 @@ #include #include "base/check_op.h" +#include "base/sequence_token.h" #include "third_party/abseil-cpp/absl/base/attributes.h" namespace base { @@ -26,6 +27,7 @@ SequenceLocalStorageMap::~SequenceLocalStorageMap() = default; // static SequenceLocalStorageMap& SequenceLocalStorageMap::GetForCurrentThread() { + CHECK(!CurrentTaskIsRunningSynchronously()); DCHECK(IsSetForCurrentThread()) << "SequenceLocalStorageSlot cannot be used because no " "SequenceLocalStorageMap was stored in TLS. Use " diff --git a/naiveproxy/src/base/threading/thread_id_name_manager.cc b/naiveproxy/src/base/threading/thread_id_name_manager.cc index 338dacb3cd..2352e13645 100644 --- a/naiveproxy/src/base/threading/thread_id_name_manager.cc +++ b/naiveproxy/src/base/threading/thread_id_name_manager.cc @@ -127,11 +127,13 @@ void ThreadIdNameManager::RemoveName(PlatformThreadHandle::Handle handle, AutoLock locked(lock_); auto handle_to_name_iter = thread_handle_to_interned_name_.find(handle); - DCHECK(handle_to_name_iter != thread_handle_to_interned_name_.end()); + CHECK(handle_to_name_iter != thread_handle_to_interned_name_.end(), + base::NotFatalUntil::M125); thread_handle_to_interned_name_.erase(handle_to_name_iter); auto id_to_handle_iter = thread_id_to_handle_.find(id); - DCHECK((id_to_handle_iter!= thread_id_to_handle_.end())); + CHECK(id_to_handle_iter != thread_id_to_handle_.end(), + base::NotFatalUntil::M125); // The given |id| may have been re-used by the system. Make sure the // mapping points to the provided |handle| before removal. if (id_to_handle_iter->second != handle) diff --git a/naiveproxy/src/base/threading/thread_restrictions.h b/naiveproxy/src/base/threading/thread_restrictions.h index 310851d978..0c6f557a44 100644 --- a/naiveproxy/src/base/threading/thread_restrictions.h +++ b/naiveproxy/src/base/threading/thread_restrictions.h @@ -167,10 +167,12 @@ class VizCompositorThreadRunnerWebView; namespace ash { class BrowserDataBackMigrator; class LoginEventRecorder; -class MojoUtils; class StartupCustomizationDocument; class StartupUtils; bool CameraAppUIShouldEnableLocalOverride(const std::string&); +namespace converters::diagnostics { +class MojoUtils; +} namespace system { class StatisticsProviderImpl; } // namespace system @@ -568,6 +570,7 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedAllowBlocking { // This can only be instantiated by friends. Use ScopedAllowBlockingForTesting // in unit tests to avoid the friend requirement. // Sorted by class name (with namespace), #if blocks at the bottom. + friend class ::BrowserProcessImpl; friend class ::BrowserThemePack; // http://crbug.com/80206 friend class ::DesktopNotificationBalloon; friend class ::FirefoxProfileLock; @@ -580,9 +583,9 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedAllowBlocking { friend class android_webview::ScopedAllowInitGLBindings; friend class ash::BrowserDataBackMigrator; friend class ash::LoginEventRecorder; - friend class ash::MojoUtils; // http://crbug.com/1055467 friend class ash::StartupCustomizationDocument; // http://crosbug.com/11103 friend class ash::StartupUtils; + friend class ash::converters::diagnostics::MojoUtils; // http://b/322741627 friend class base::AdjustOOMScoreHelper; friend class base::ChromeOSVersionInfo; friend class base::Process; @@ -785,8 +788,6 @@ class BASE_EXPORT [[maybe_unused, nodiscard]] ScopedAllowBaseSyncPrimitives { // Usage that should be fixed: // Sorted by class name (with namespace). friend class ::NativeBackendKWallet; // http://crbug.com/125331 - friend class ::ash::system:: - StatisticsProviderImpl; // http://crbug.com/125385 friend class blink::VideoFrameResourceProvider; // http://crbug.com/878070 ScopedAllowBaseSyncPrimitives() DEFAULT_IF_DCHECK_IS_OFF; @@ -864,6 +865,7 @@ class BASE_EXPORT friend class vr::VrShell; // Usage that should be fixed: + friend class ::ash::system::StatisticsProviderImpl; // http://b/261818124 friend class ::chromeos::BlockingMethodCaller; // http://crbug.com/125360 friend class base::Thread; // http://crbug.com/918039 friend class cc::CompletionEvent; // http://crbug.com/902653 diff --git a/naiveproxy/src/base/time/time.h b/naiveproxy/src/base/time/time.h index d8fef0bbab..dbae325572 100644 --- a/naiveproxy/src/base/time/time.h +++ b/naiveproxy/src/base/time/time.h @@ -116,7 +116,9 @@ struct TimeSpan; namespace base { +#if BUILDFLAG(IS_WIN) class PlatformThreadHandle; +#endif class TimeDelta; template diff --git a/naiveproxy/src/base/trace_event/base_tracing_forward.h b/naiveproxy/src/base/trace_event/base_tracing_forward.h index 7b29f4dfb8..effcb9782f 100644 --- a/naiveproxy/src/base/trace_event/base_tracing_forward.h +++ b/naiveproxy/src/base/trace_event/base_tracing_forward.h @@ -5,8 +5,8 @@ #ifndef BASE_TRACE_EVENT_BASE_TRACING_FORWARD_H_ #define BASE_TRACE_EVENT_BASE_TRACING_FORWARD_H_ -// Proxy header that provides //base code access to forward-declarations for -// classes and functions defined in base_tracing.h. +// This header is a wrapper around perfetto's traced_value_forward.h that +// handles Chromium's ENABLE_BASE_TRACING buildflag. #include "base/tracing_buildflags.h" @@ -34,13 +34,4 @@ struct check_traced_value_support { #endif // !BUILDFLAG(ENABLE_BASE_TRACING) -namespace base { -namespace trace_event { - -class ConvertableToTraceFormat; -class TracedValue; - -} // namespace trace_event -} // namespace base - #endif // BASE_TRACE_EVENT_BASE_TRACING_FORWARD_H_ diff --git a/naiveproxy/src/base/trace_event/builtin_categories.h b/naiveproxy/src/base/trace_event/builtin_categories.h index f82e41ee24..5f6efb0e93 100644 --- a/naiveproxy/src/base/trace_event/builtin_categories.h +++ b/naiveproxy/src/base/trace_event/builtin_categories.h @@ -387,6 +387,7 @@ X("v8,devtools.timeline," TRACE_DISABLED_BY_DEFAULT("v8.compile")) \ X("viz,benchmark") \ X("viz,benchmark,graphics.pipeline") \ + X("wakeup.flow,toplevel.flow") \ X("WebCore,benchmark,rail") \ X(TRACE_DISABLED_BY_DEFAULT("cc.debug") "," TRACE_DISABLED_BY_DEFAULT( \ "viz.quads") "," TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers")) \ diff --git a/naiveproxy/src/base/trace_event/etw_interceptor_win.cc b/naiveproxy/src/base/trace_event/etw_interceptor_win.cc index 429062adba..5945bb5504 100644 --- a/naiveproxy/src/base/trace_event/etw_interceptor_win.cc +++ b/naiveproxy/src/base/trace_event/etw_interceptor_win.cc @@ -16,8 +16,10 @@ namespace base::trace_event { class ETWInterceptor::Delegate : public perfetto::TrackEventStateTracker::Delegate { public: - explicit Delegate(InterceptorContext& context) - : context_(&context), locked_self_(context_->GetInterceptorLocked()) {} + explicit Delegate(perfetto::LockedHandle locked_self) + : locked_self_(std::move(locked_self)) { + DCHECK(locked_self_); + } ~Delegate() override; perfetto::TrackEventStateTracker::SessionState* GetSessionState() override; @@ -27,7 +29,6 @@ class ETWInterceptor::Delegate const perfetto::TrackEventStateTracker::ParsedTrackEvent&) override; private: - raw_ptr context_; perfetto::LockedHandle locked_self_; }; @@ -95,7 +96,12 @@ void ETWInterceptor::Register(TlmProvider* provider) { void ETWInterceptor::OnTracePacket(InterceptorContext context) { auto& tls = context.GetThreadLocalState(); - Delegate delegate(context); + perfetto::LockedHandle locked_self = + context.GetInterceptorLocked(); + if (!locked_self) { + return; + } + Delegate delegate(std::move(locked_self)); perfetto::protos::pbzero::TracePacket::Decoder packet( context.packet_data.data, context.packet_data.size); perfetto::TrackEventStateTracker::ProcessTracePacket( diff --git a/naiveproxy/src/base/trace_event/log_message.cc b/naiveproxy/src/base/trace_event/log_message.cc index 0af9d7792d..a8d3bdfbdd 100644 --- a/naiveproxy/src/base/trace_event/log_message.cc +++ b/naiveproxy/src/base/trace_event/log_message.cc @@ -7,6 +7,7 @@ #include #include +#include #include "base/json/string_escape.h" #include "base/notreached.h" @@ -15,7 +16,7 @@ namespace base { namespace trace_event { -LogMessage::LogMessage(const char* file, base::StringPiece message, int line) +LogMessage::LogMessage(const char* file, std::string_view message, int line) : file_(file), message_(message), line_number_(line) {} LogMessage::~LogMessage() = default; diff --git a/naiveproxy/src/base/trace_event/log_message.h b/naiveproxy/src/base/trace_event/log_message.h index dbde68f2b6..348a69a5bd 100644 --- a/naiveproxy/src/base/trace_event/log_message.h +++ b/naiveproxy/src/base/trace_event/log_message.h @@ -8,9 +8,9 @@ #include #include +#include #include "base/base_export.h" -#include "base/strings/string_piece.h" #include "base/trace_event/trace_event_impl.h" namespace base { @@ -19,7 +19,7 @@ namespace trace_event { class BASE_EXPORT LogMessage : public ConvertableToTraceFormat { public: - LogMessage(const char* file, base::StringPiece message, int line); + LogMessage(const char* file, std::string_view message, int line); LogMessage(const LogMessage&) = delete; LogMessage& operator=(const LogMessage&) = delete; ~LogMessage() override; diff --git a/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc b/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc index 937cec766d..de84c8f352 100644 --- a/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc +++ b/naiveproxy/src/base/trace_event/memory_infra_background_allowlist.cc @@ -7,6 +7,7 @@ #include #include +#include #include "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_buildflags.h" #include "base/containers/fixed_flat_set.h" @@ -28,7 +29,7 @@ namespace { // TODO(ssid): Some dump providers do not create ownership edges on background // dump. So, the effective size will not be correct. constexpr auto kDumpProviderAllowlist = - base::MakeFixedFlatSet({ + base::MakeFixedFlatSet({ // clang-format off #if BUILDFLAG(IS_ANDROID) base::android::MeminfoDumpProvider::kDumpProviderName, @@ -97,7 +98,7 @@ constexpr auto kDumpProviderAllowlist = // A list of string names that are allowed for the memory allocator dumps in // background mode. constexpr auto kAllocatorDumpNameAllowlist = - base::MakeFixedFlatSet({ + base::MakeFixedFlatSet({ // clang-format off // Some of the blink values vary based on compile time flags. The // compile time flags are not in base, so all are listed here. diff --git a/naiveproxy/src/base/trace_event/named_trigger.cc b/naiveproxy/src/base/trace_event/named_trigger.cc new file mode 100644 index 0000000000..84bd2a1c00 --- /dev/null +++ b/naiveproxy/src/base/trace_event/named_trigger.cc @@ -0,0 +1,26 @@ +// Copyright 2024 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/trace_event/named_trigger.h" + +#include "base/check.h" + +namespace base::trace_event { + +// |g_named_trigger_manager| is intentionally leaked on shutdown. +NamedTriggerManager* g_named_trigger_manager = nullptr; + +bool EmitNamedTrigger(const std::string& trigger_name) { + if (g_named_trigger_manager) { + return g_named_trigger_manager->DoEmitNamedTrigger(trigger_name); + } + return false; +} + +void NamedTriggerManager::SetInstance(NamedTriggerManager* manager) { + DCHECK(g_named_trigger_manager == nullptr || manager == nullptr); + g_named_trigger_manager = manager; +} + +} // namespace base::trace_event diff --git a/naiveproxy/src/base/trace_event/named_trigger.h b/naiveproxy/src/base/trace_event/named_trigger.h new file mode 100644 index 0000000000..092fecc6a5 --- /dev/null +++ b/naiveproxy/src/base/trace_event/named_trigger.h @@ -0,0 +1,31 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TRACE_EVENT_NAMED_TRIGGER_H_ +#define BASE_TRACE_EVENT_NAMED_TRIGGER_H_ + +#include + +#include "base/base_export.h" + +namespace base::trace_event { + +// Notifies that a manual trigger event has occurred. Returns true if the +// trigger caused a scenario to either begin recording or finalize the trace +// depending on the config, or false if the trigger had no effect. If the +// trigger specified isn't active in the config, this will do nothing. +BASE_EXPORT bool EmitNamedTrigger(const std::string& trigger_name); + +class NamedTriggerManager { + public: + virtual bool DoEmitNamedTrigger(const std::string& trigger_name) = 0; + + protected: + // Sets the instance returns by GetInstance() globally to |manager|. + BASE_EXPORT static void SetInstance(NamedTriggerManager* manager); +}; + +} // namespace base::trace_event + +#endif // BASE_TRACE_EVENT_NAMED_TRIGGER_H_ diff --git a/naiveproxy/src/base/trace_event/process_memory_dump.cc b/naiveproxy/src/base/trace_event/process_memory_dump.cc index bff7090c33..71c458cfbf 100644 --- a/naiveproxy/src/base/trace_event/process_memory_dump.cc +++ b/naiveproxy/src/base/trace_event/process_memory_dump.cc @@ -14,6 +14,7 @@ #include "base/memory/page_size.h" #include "base/memory/ptr_util.h" #include "base/memory/shared_memory_tracker.h" +#include "base/notimplemented.h" #include "base/process/process_metrics.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" diff --git a/naiveproxy/src/base/trace_event/trace_config_category_filter.cc b/naiveproxy/src/base/trace_event/trace_config_category_filter.cc index 473efade68..9c3a7c0dda 100644 --- a/naiveproxy/src/base/trace_event/trace_config_category_filter.cc +++ b/naiveproxy/src/base/trace_event/trace_config_category_filter.cc @@ -84,8 +84,7 @@ bool TraceConfigCategoryFilter::IsCategoryGroupEnabled( const StringPiece& category_group_name) const { bool had_enabled_by_default = false; DCHECK(!category_group_name.empty()); - CStringTokenizer category_group_tokens(category_group_name.begin(), - category_group_name.end(), ","); + StringViewTokenizer category_group_tokens(category_group_name, ","); while (category_group_tokens.GetNext()) { StringPiece category_group_token = category_group_tokens.token_piece(); // Don't allow empty tokens, nor tokens with leading or trailing space. diff --git a/naiveproxy/src/base/trace_event/trace_event_stub.h b/naiveproxy/src/base/trace_event/trace_event_stub.h index 26907a8955..edd27cc80f 100644 --- a/naiveproxy/src/base/trace_event/trace_event_stub.h +++ b/naiveproxy/src/base/trace_event/trace_event_stub.h @@ -10,11 +10,10 @@ #include #include #include +#include #include "base/base_export.h" #include "base/check.h" -#include "base/memory/ref_counted.h" -#include "base/strings/string_piece.h" #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/memory_allocator_dump_guid.h" #include "base/values.h" @@ -104,24 +103,23 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { void SetInteger(const char* name, int value) {} void SetDouble(const char* name, double value) {} void SetBoolean(const char* name, bool value) {} - void SetString(const char* name, base::StringPiece value) {} + void SetString(const char* name, std::string_view value) {} void SetValue(const char* name, TracedValue* value) {} void BeginDictionary(const char* name) {} void BeginArray(const char* name) {} - void SetIntegerWithCopiedName(base::StringPiece name, int value) {} - void SetDoubleWithCopiedName(base::StringPiece name, double value) {} - void SetBooleanWithCopiedName(base::StringPiece name, bool value) {} - void SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value) {} - void SetValueWithCopiedName(base::StringPiece name, TracedValue* value) {} - void BeginDictionaryWithCopiedName(base::StringPiece name) {} - void BeginArrayWithCopiedName(base::StringPiece name) {} + void SetIntegerWithCopiedName(std::string_view name, int value) {} + void SetDoubleWithCopiedName(std::string_view name, double value) {} + void SetBooleanWithCopiedName(std::string_view name, bool value) {} + void SetStringWithCopiedName(std::string_view name, std::string_view value) {} + void SetValueWithCopiedName(std::string_view name, TracedValue* value) {} + void BeginDictionaryWithCopiedName(std::string_view name) {} + void BeginArrayWithCopiedName(std::string_view name) {} void AppendInteger(int) {} void AppendDouble(double) {} void AppendBoolean(bool) {} - void AppendString(base::StringPiece) {} + void AppendString(std::string_view) {} void BeginArray() {} void BeginDictionary() {} diff --git a/naiveproxy/src/base/trace_event/trace_log.cc b/naiveproxy/src/base/trace_event/trace_log.cc index 03e14fcd1c..3eafd49386 100644 --- a/naiveproxy/src/base/trace_event/trace_log.cc +++ b/naiveproxy/src/base/trace_event/trace_log.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,6 @@ #include "base/process/process_metrics.h" #include "base/ranges/algorithm.h" #include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/strings/stringprintf.h" @@ -2012,7 +2012,7 @@ void TraceLog::AddMetadataEventsWhileLocked() { #endif if (!process_labels_.empty()) { - std::vector labels; + std::vector labels; for (const auto& it : process_labels_) labels.push_back(it.second); AddMetadataEventWhileLocked(current_thread_id, "process_labels", "labels", diff --git a/naiveproxy/src/base/trace_event/traced_value.cc b/naiveproxy/src/base/trace_event/traced_value.cc index 2f3722d066..d8228d0d20 100644 --- a/naiveproxy/src/base/trace_event/traced_value.cc +++ b/naiveproxy/src/base/trace_event/traced_value.cc @@ -8,6 +8,7 @@ #include #include +#include #include #include "base/bits.h" @@ -68,7 +69,7 @@ inline void WriteKeyNameAsRawPtr(Pickle& pickle, const char* ptr) { pickle.WriteUInt64(static_cast(reinterpret_cast(ptr))); } -inline void WriteKeyNameWithCopy(Pickle& pickle, base::StringPiece str) { +inline void WriteKeyNameWithCopy(Pickle& pickle, std::string_view str) { pickle.WriteBytes(as_bytes(make_span(&kTypeString, 1u))); pickle.WriteString(str); } @@ -105,7 +106,7 @@ class PickleWriter final : public TracedValue::Writer { WriteKeyNameAsRawPtr(pickle_, name); } - void SetIntegerWithCopiedName(base::StringPiece name, int value) override { + void SetIntegerWithCopiedName(std::string_view name, int value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeInt, 1u))); pickle_.WriteInt(value); WriteKeyNameWithCopy(pickle_, name); @@ -117,7 +118,7 @@ class PickleWriter final : public TracedValue::Writer { WriteKeyNameAsRawPtr(pickle_, name); } - void SetDoubleWithCopiedName(base::StringPiece name, double value) override { + void SetDoubleWithCopiedName(std::string_view name, double value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeDouble, 1u))); pickle_.WriteDouble(value); WriteKeyNameWithCopy(pickle_, name); @@ -129,43 +130,40 @@ class PickleWriter final : public TracedValue::Writer { WriteKeyNameAsRawPtr(pickle_, name); } - void SetBooleanWithCopiedName(base::StringPiece name, bool value) override { + void SetBooleanWithCopiedName(std::string_view name, bool value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeBool, 1u))); pickle_.WriteBool(value); WriteKeyNameWithCopy(pickle_, name); } - void SetString(const char* name, base::StringPiece value) override { + void SetString(const char* name, std::string_view value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeString, 1u))); pickle_.WriteString(value); WriteKeyNameAsRawPtr(pickle_, name); } - void SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value) override { + void SetStringWithCopiedName(std::string_view name, + std::string_view value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeString, 1u))); pickle_.WriteString(value); WriteKeyNameWithCopy(pickle_, name); } void SetValue(const char* name, Writer* value) override { - DCHECK(value->IsPickleWriter()); + CHECK(value->IsPickleWriter()); const PickleWriter* pickle_writer = static_cast(value); BeginDictionary(name); - pickle_.WriteBytes(pickle_writer->pickle_.payload(), - pickle_writer->pickle_.payload_size()); + pickle_.WriteBytes(pickle_writer->pickle_.payload_bytes()); EndDictionary(); } - void SetValueWithCopiedName(base::StringPiece name, Writer* value) override { - DCHECK(value->IsPickleWriter()); + void SetValueWithCopiedName(std::string_view name, Writer* value) override { + CHECK(value->IsPickleWriter()); const PickleWriter* pickle_writer = static_cast(value); BeginDictionaryWithCopiedName(name); - pickle_.WriteBytes( - as_bytes(make_span(pickle_writer->pickle_.payload(), - pickle_writer->pickle_.payload_size()))); + pickle_.WriteBytes(pickle_writer->pickle_.payload_bytes()); EndDictionary(); } @@ -182,7 +180,7 @@ class PickleWriter final : public TracedValue::Writer { WriteKeyNameAsRawPtr(pickle_, name); } - void BeginDictionaryWithCopiedName(base::StringPiece name) override { + void BeginDictionaryWithCopiedName(std::string_view name) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeStartDict, 1u))); WriteKeyNameWithCopy(pickle_, name); } @@ -192,7 +190,7 @@ class PickleWriter final : public TracedValue::Writer { WriteKeyNameAsRawPtr(pickle_, name); } - void BeginArrayWithCopiedName(base::StringPiece name) override { + void BeginArrayWithCopiedName(std::string_view name) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeStartArray, 1u))); WriteKeyNameWithCopy(pickle_, name); } @@ -219,7 +217,7 @@ class PickleWriter final : public TracedValue::Writer { pickle_.WriteBool(value); } - void AppendString(base::StringPiece value) override { + void AppendString(std::string_view value) override { pickle_.WriteBytes(as_bytes(make_span(&kTypeString, 1u))); pickle_.WriteString(value); } @@ -495,7 +493,7 @@ void TracedValue::SetInteger(const char* name, int value) { writer_->SetInteger(name, value); } -void TracedValue::SetIntegerWithCopiedName(base::StringPiece name, int value) { +void TracedValue::SetIntegerWithCopiedName(std::string_view name, int value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetIntegerWithCopiedName(name, value); } @@ -505,8 +503,7 @@ void TracedValue::SetDouble(const char* name, double value) { writer_->SetDouble(name, value); } -void TracedValue::SetDoubleWithCopiedName(base::StringPiece name, - double value) { +void TracedValue::SetDoubleWithCopiedName(std::string_view name, double value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetDoubleWithCopiedName(name, value); } @@ -516,18 +513,18 @@ void TracedValue::SetBoolean(const char* name, bool value) { writer_->SetBoolean(name, value); } -void TracedValue::SetBooleanWithCopiedName(base::StringPiece name, bool value) { +void TracedValue::SetBooleanWithCopiedName(std::string_view name, bool value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetBooleanWithCopiedName(name, value); } -void TracedValue::SetString(const char* name, base::StringPiece value) { +void TracedValue::SetString(const char* name, std::string_view value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetString(name, value); } -void TracedValue::SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value) { +void TracedValue::SetStringWithCopiedName(std::string_view name, + std::string_view value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetStringWithCopiedName(name, value); } @@ -537,7 +534,7 @@ void TracedValue::SetValue(const char* name, TracedValue* value) { writer_->SetValue(name, value->writer_.get()); } -void TracedValue::SetValueWithCopiedName(base::StringPiece name, +void TracedValue::SetValueWithCopiedName(std::string_view name, TracedValue* value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetValueWithCopiedName(name, value->writer_.get()); @@ -559,7 +556,7 @@ void TracedValue::SetPointer(const char* name, const void* value) { writer_->SetString(name, PointerToString(value)); } -void TracedValue::SetPointerWithCopiedName(base::StringPiece name, +void TracedValue::SetPointerWithCopiedName(std::string_view name, const void* value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); writer_->SetStringWithCopiedName(name, PointerToString(value)); @@ -571,7 +568,7 @@ void TracedValue::BeginDictionary(const char* name) { writer_->BeginDictionary(name); } -void TracedValue::BeginDictionaryWithCopiedName(base::StringPiece name) { +void TracedValue::BeginDictionaryWithCopiedName(std::string_view name) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); DEBUG_PUSH_CONTAINER(kStackTypeDict); writer_->BeginDictionaryWithCopiedName(name); @@ -583,7 +580,7 @@ void TracedValue::BeginArray(const char* name) { writer_->BeginArray(name); } -void TracedValue::BeginArrayWithCopiedName(base::StringPiece name) { +void TracedValue::BeginArrayWithCopiedName(std::string_view name) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeDict); DEBUG_PUSH_CONTAINER(kStackTypeArray); writer_->BeginArrayWithCopiedName(name); @@ -604,7 +601,7 @@ void TracedValue::AppendBoolean(bool value) { writer_->AppendBoolean(value); } -void TracedValue::AppendString(base::StringPiece value) { +void TracedValue::AppendString(std::string_view value) { DCHECK_CURRENT_CONTAINER_IS(kStackTypeArray); writer_->AppendString(value); } @@ -703,7 +700,7 @@ TracedValue::ValueHolder::ValueHolder(bool value) { kept_value_type_ = KeptValueType::kBoolType; } -TracedValue::ValueHolder::ValueHolder(base::StringPiece value) { +TracedValue::ValueHolder::ValueHolder(std::string_view value) { kept_value_.string_piece_value = value; kept_value_type_ = KeptValueType::kStringPieceType; } @@ -911,7 +908,7 @@ TracedValue::ArrayScope TracedValue::BeginArrayScoped(const char* name) { } TracedValue::ArrayScope TracedValue::BeginArrayScopedWithCopiedName( - base::StringPiece name) { + std::string_view name) { BeginArrayWithCopiedName(name); return TracedValue::ArrayScope(this); } @@ -935,7 +932,7 @@ TracedValue::DictionaryScope TracedValue::BeginDictionaryScoped( } TracedValue::DictionaryScope TracedValue::BeginDictionaryScopedWithCopiedName( - base::StringPiece name) { + std::string_view name) { BeginDictionaryWithCopiedName(name); return TracedValue::DictionaryScope(this); } diff --git a/naiveproxy/src/base/trace_event/traced_value.h b/naiveproxy/src/base/trace_event/traced_value.h index 0178d262e8..428262e727 100644 --- a/naiveproxy/src/base/trace_event/traced_value.h +++ b/naiveproxy/src/base/trace_event/traced_value.h @@ -10,21 +10,22 @@ #include #include #include +#include #include #include "base/base_export.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ptr_exclusion.h" -#include "base/strings/string_piece.h" #include "base/trace_event/trace_arguments.h" namespace base { -class TraceEventMemoryOverhead; class Value; namespace trace_event { +class TraceEventMemoryOverhead; + class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { public: // TODO(oysteine): |capacity| is not used in any production code. Consider @@ -41,26 +42,26 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { void SetInteger(const char* name, int value); void SetDouble(const char* name, double value); void SetBoolean(const char* name, bool value); - void SetString(const char* name, base::StringPiece value); + void SetString(const char* name, std::string_view value); void SetValue(const char* name, TracedValue* value); void SetPointer(const char* name, const void* value); void BeginDictionary(const char* name); void BeginArray(const char* name); // These, instead, can be safely passed a temporary string. - void SetIntegerWithCopiedName(base::StringPiece name, int value); - void SetDoubleWithCopiedName(base::StringPiece name, double value); - void SetBooleanWithCopiedName(base::StringPiece name, bool value); - void SetStringWithCopiedName(base::StringPiece name, base::StringPiece value); - void SetValueWithCopiedName(base::StringPiece name, TracedValue* value); - void SetPointerWithCopiedName(base::StringPiece name, const void* value); - void BeginDictionaryWithCopiedName(base::StringPiece name); - void BeginArrayWithCopiedName(base::StringPiece name); + void SetIntegerWithCopiedName(std::string_view name, int value); + void SetDoubleWithCopiedName(std::string_view name, double value); + void SetBooleanWithCopiedName(std::string_view name, bool value); + void SetStringWithCopiedName(std::string_view name, std::string_view value); + void SetValueWithCopiedName(std::string_view name, TracedValue* value); + void SetPointerWithCopiedName(std::string_view name, const void* value); + void BeginDictionaryWithCopiedName(std::string_view name); + void BeginArrayWithCopiedName(std::string_view name); void AppendInteger(int); void AppendDouble(double); void AppendBoolean(bool); - void AppendString(base::StringPiece); + void AppendString(std::string_view); void AppendPointer(const void*); void BeginArray(); void BeginDictionary(); @@ -112,7 +113,7 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { [[nodiscard]] ArrayScope AppendArrayScoped(); [[nodiscard]] ArrayScope BeginArrayScoped(const char* name); [[nodiscard]] ArrayScope BeginArrayScopedWithCopiedName( - base::StringPiece name); + std::string_view name); // Helper to auto-close a dictionary. The call to // |DictionaryScope::~DictionaryScope| closes the dictionary. @@ -155,7 +156,7 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { [[nodiscard]] DictionaryScope AppendDictionaryScoped(); [[nodiscard]] DictionaryScope BeginDictionaryScoped(const char* name); [[nodiscard]] DictionaryScope BeginDictionaryScopedWithCopiedName( - base::StringPiece name); + std::string_view name); class BASE_EXPORT Array; class BASE_EXPORT Dictionary; @@ -169,7 +170,7 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { // the value is also a |std::initializer_list|). Generally the helper types // |TracedValue::Dictionary|, |TracedValue::Array|, // |TracedValue::DictionaryItem|, |TracedValue::ArrayItem| must be valid as - // well as their internals (e.g., |base::StringPiece| data should be valid + // well as their internals (e.g., |std::string_view| data should be valid // when |TracedValue::Build| is called; |TracedValue::Array| or // |TracedValue::Dictionary| holds a |std::initializer_list| whose underlying // array needs to be valid when calling |TracedValue::Build|). @@ -237,7 +238,7 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { // StringPiece's backing storage / const char* pointer needs to remain valid // until TracedValue::Build is called. // NOLINTNEXTLINE(google-explicit-constructor) - ValueHolder(base::StringPiece value); + ValueHolder(std::string_view value); // Create a copy to avoid holding a reference to a non-existing string: // // Example: @@ -248,13 +249,13 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { // 3. |Build| iterates initializer_list of |DictionaryItems|. // // If the original |ValueHolder| kept just a reference to the string (or - // a |base::StringPiece|) then |Build| is undefined behaviour, as it is + // a |std::string_view|) then |Build| is undefined behaviour, as it is // passing a reference to an out-of-scope temporary to // |TracedValue::SetString|. // NOLINTNEXTLINE(google-explicit-constructor) ValueHolder(std::string value); // Define an explicit overload for const char* to resolve the ambiguity - // between the base::StringPiece, void*, and bool constructors for string + // between the std::string_view, void*, and bool constructors for string // literals. ValueHolder(const char* value); // NOLINT(google-explicit-constructor) ValueHolder(Array& value); // NOLINT(google-explicit-constructor) @@ -272,7 +273,7 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { int int_value; double double_value; bool bool_value; - base::StringPiece string_piece_value; + std::string_view string_piece_value; std::string std_string_value; // This field is not a raw_ptr<> because it was filtered by the rewriter // for: #union @@ -349,29 +350,28 @@ class BASE_EXPORT TracedValue : public ConvertableToTraceFormat { virtual void SetInteger(const char* name, int value) = 0; virtual void SetDouble(const char* name, double value) = 0; virtual void SetBoolean(const char* name, bool value) = 0; - virtual void SetString(const char* name, base::StringPiece value) = 0; + virtual void SetString(const char* name, std::string_view value) = 0; virtual void SetValue(const char* name, Writer* value) = 0; virtual void BeginDictionary(const char* name) = 0; virtual void BeginArray(const char* name) = 0; // These, instead, can be safely passed a temporary string. - virtual void SetIntegerWithCopiedName(base::StringPiece name, - int value) = 0; - virtual void SetDoubleWithCopiedName(base::StringPiece name, + virtual void SetIntegerWithCopiedName(std::string_view name, int value) = 0; + virtual void SetDoubleWithCopiedName(std::string_view name, double value) = 0; - virtual void SetBooleanWithCopiedName(base::StringPiece name, + virtual void SetBooleanWithCopiedName(std::string_view name, bool value) = 0; - virtual void SetStringWithCopiedName(base::StringPiece name, - base::StringPiece value) = 0; - virtual void SetValueWithCopiedName(base::StringPiece name, + virtual void SetStringWithCopiedName(std::string_view name, + std::string_view value) = 0; + virtual void SetValueWithCopiedName(std::string_view name, Writer* value) = 0; - virtual void BeginDictionaryWithCopiedName(base::StringPiece name) = 0; - virtual void BeginArrayWithCopiedName(base::StringPiece name) = 0; + virtual void BeginDictionaryWithCopiedName(std::string_view name) = 0; + virtual void BeginArrayWithCopiedName(std::string_view name) = 0; virtual void AppendInteger(int) = 0; virtual void AppendDouble(double) = 0; virtual void AppendBoolean(bool) = 0; - virtual void AppendString(base::StringPiece) = 0; + virtual void AppendString(std::string_view) = 0; virtual void AppendAsTraceFormat(std::string* out) const = 0; diff --git a/naiveproxy/src/base/trace_event/traced_value_support.h b/naiveproxy/src/base/trace_event/traced_value_support.h index 500e6133c0..0e5867975a 100644 --- a/naiveproxy/src/base/trace_event/traced_value_support.h +++ b/naiveproxy/src/base/trace_event/traced_value_support.h @@ -11,7 +11,7 @@ #include "base/memory/raw_ref.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" -#include "base/strings/string_piece.h" + #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/unguessable_token.h" @@ -175,7 +175,7 @@ struct TraceFormatTraits { static void WriteIntoTrace(perfetto::TracedValue context, const char16_t value[N]) { return std::move(context).WriteString( - ::base::UTF16ToUTF8(::base::StringPiece16(value))); + ::base::UTF16ToUTF8(::std::u16string_view(value))); } }; @@ -184,7 +184,7 @@ struct TraceFormatTraits { static void WriteIntoTrace(perfetto::TracedValue context, const char16_t* value) { return std::move(context).WriteString( - ::base::UTF16ToUTF8(::base::StringPiece16(value))); + ::base::UTF16ToUTF8(::std::u16string_view(value))); } }; @@ -215,11 +215,11 @@ struct TraceFormatTraits { } }; -// base::StringPiece support. +// std::string_view support. template <> -struct TraceFormatTraits<::base::StringPiece16> { +struct TraceFormatTraits<::std::u16string_view> { static void WriteIntoTrace(perfetto::TracedValue context, - ::base::StringPiece16 value) { + ::std::u16string_view value) { return std::move(context).WriteString(::base::UTF16ToUTF8(value)); } }; diff --git a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto index e934dc1214..a5d6977f41 100644 --- a/naiveproxy/src/base/tracing/protos/chrome_track_event.proto +++ b/naiveproxy/src/base/tracing/protos/chrome_track_event.proto @@ -37,6 +37,7 @@ message BlinkTaskScope { TASK_SCOPE_POP_STATE = 5; TASK_SCOPE_SCHEDULER_POST_TASK = 6; TASK_SCOPE_REQUEST_IDLE_CALLBACK = 7; + TASK_SCOPE_XML_HTTP_REQUEST = 8; } optional TaskScopeType type = 1; optional int64 scope_task_id = 2; @@ -86,6 +87,8 @@ message ChromeRasterTask { message ChromeMessagePumpForUI { // The MSG defined in winuser.h. optional uint32 message_id = 1; + // The result of the Win32 API call WaitForMultipleObjectsEx(). + optional uint32 wait_for_object_result = 2; } // An enumeration specifying the reason of the RenderFrame deletion. @@ -1072,7 +1075,7 @@ message BlinkExecutionContext { WORLD_MAIN = 1; WORLD_ISOLATED = 2; WORLD_INSPECTOR_ISOLATED = 3; - WORLD_BLINK_INTERNAL_NON_JS_EXPOSED = 4; + WORLD_REG_EXP = 4; WORLD_FOR_V8_CONTEXT_SNAPSHOT_NON_MAIN = 5; WORLD_WORKER = 6; WORLD_SHADOW_REALM = 7; @@ -1385,6 +1388,14 @@ message ChromeGraphicsPipeline { STEP_BUFFER_SWAP_POST_SUBMIT = 12; STEP_FINISH_BUFFER_SWAP = 13; STEP_SWAP_BUFFERS_ACK = 14; + + // Frame submission stages when Exo (Wayland server implementation in Ash + // browser process) is involved. Wayland clients (such as Lacros or ARC++) + // submit visual contents via Wayland surface commits, with which Exo + // constructs compositor frames and forwards to Ash Viz. + STEP_EXO_CONSTRUCT_COMPOSITOR_FRAME = 15; + STEP_EXO_SUBMIT_COMPOSITOR_FRAME = 16; + STEP_EXO_DISCARD_COMPOSITOR_FRAME = 17; } enum FrameSkippedReason { SKIPPED_REASON_UNKNOWN = 0; @@ -1514,16 +1525,36 @@ message EventForwarder { // The events getHistorySize(). optional int32 history_size = 1; // The time of the oldest event (getHistoricalEventTimeNanos(0)). - optional int64 time_ns = 2; + optional int64 oldest_time_ns = 2; + // The time of the newest event (getEventTimeNanos(0)). + optional int64 latest_time_ns = 5; // The X coordinate of the event as reported by MotionEvent.getX(). optional float x_pixel = 3; // The Y coordinate of the event as reported by MotionEvent.getY(). optional float y_pixel = 4; + // Determine if the previous forwarded event changed x coordinate. + optional bool has_x_movement = 6; + // Determine if the previous forwarded event changed y coordinate. + optional bool has_y_movement = 7; +} + +// TouchDispositionGestureFilter is a class on android that detects and forwards +// along gesture events based on touch acks and other information. +message TouchDispositionGestureFilter { + // The number of gesture's inside of a GestureEventDataPacket. + optional int32 gesture_count = 1; +} + +message ViewClassName { + // The name associated with a View class in browser UI. The class name is set + // by the view class itself through metadata macros and contains no data that + // can be modified by a user. + optional string name = 1; } message ChromeTrackEvent { // Extension range for Chrome: 1000-1999 - // Next ID: 1059 + // Next ID: 1061 extend TrackEvent { optional ChromeAppState chrome_app_state = 1000; @@ -1649,5 +1680,10 @@ message ChromeTrackEvent { optional WebContentInteraction web_content_interaction = 1058; optional EventForwarder event_forwarder = 1059; + + optional TouchDispositionGestureFilter touch_disposition_gesture_filter = + 1060; + + optional ViewClassName view_class_name = 1061; } } diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/cpu_powerups.sql b/naiveproxy/src/base/tracing/stdlib/chrome/cpu_powerups.sql index 3d51765a38..8657ca506a 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/cpu_powerups.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/cpu_powerups.sql @@ -71,7 +71,7 @@ CREATE PERFETTO VIEW chrome_cpu_power_slice( ORDER BY ts ASC; -- We do not want scheduler slices with utid = 0 (the 'swapper' kernel thread). -CREATE PERFETTO VIEW internal_cpu_power_valid_sched_slice AS +CREATE PERFETTO VIEW _cpu_power_valid_sched_slice AS SELECT * FROM sched_slice WHERE utid != 0; @@ -90,10 +90,10 @@ CREATE PERFETTO VIEW internal_cpu_power_valid_sched_slice AS -- -- Here threads T1 and T2 executed in CPU power slice [A,B]. The -- time between F and G represents time between threads in the kernel. -CREATE VIRTUAL TABLE internal_cpu_power_and_sched_slice +CREATE VIRTUAL TABLE _cpu_power_and_sched_slice USING SPAN_JOIN(chrome_cpu_power_slice PARTITIONED cpu, - internal_cpu_power_valid_sched_slice PARTITIONED cpu); + _cpu_power_valid_sched_slice PARTITIONED cpu); -- The Linux scheduler slices that executed immediately after a -- CPU power up. @@ -121,7 +121,7 @@ SELECT utid, previous_power_state, powerup_id -FROM internal_cpu_power_and_sched_slice +FROM _cpu_power_and_sched_slice WHERE power_state = 0 -- Power-ups only. GROUP BY cpu, powerup_id HAVING ts = MIN(ts) -- There will only be one MIN sched slice @@ -137,7 +137,7 @@ ORDER BY ts ASC; -- slice_id The slice_id for the top-level slice. -- ts Starting timestamp for the slice. -- dur The duration for the slice. -CREATE PERFETTO VIEW internal_cpu_power_thread_and_toplevel_slice AS +CREATE PERFETTO VIEW _cpu_power_thread_and_toplevel_slice AS SELECT t.utid AS utid, s.id AS slice_id, @@ -164,7 +164,7 @@ CREATE PERFETTO VIEW internal_cpu_power_thread_and_toplevel_slice AS CREATE VIRTUAL TABLE chrome_cpu_power_post_powerup_slice USING SPAN_JOIN(chrome_cpu_power_first_sched_slice_after_powerup PARTITIONED utid, - internal_cpu_power_thread_and_toplevel_slice PARTITIONED utid); + _cpu_power_thread_and_toplevel_slice PARTITIONED utid); -- The first top-level slice that ran after a CPU power-up. CREATE PERFETTO VIEW chrome_cpu_power_first_toplevel_slice_after_powerup( diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/event_latency_description.sql b/naiveproxy/src/base/tracing/stdlib/chrome/event_latency_description.sql index ca89dae616..edabe7608f 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/event_latency_description.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/event_latency_description.sql @@ -146,7 +146,7 @@ VALUES 'CompositorFrame.'), ('ReceiveCompositorFrameToStartDraw', 'Interval between the first frame received to when all frames (or ' || - 'timeouts have occured) and we start drawing. It can be blocked by ' || + 'timeouts have occurred) and we start drawing. It can be blocked by ' || 'other processes (e.g to draw a toolbar it waiting for information from ' || 'the Browser) as it waits for timeouts or frames to be provided. This ' || 'is the tree of dependencies that the GPU VizCompositor is waiting for ' || diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/page_loads.sql b/naiveproxy/src/base/tracing/stdlib/chrome/page_loads.sql index 73e44e9e7f..c8d1443785 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/page_loads.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/page_loads.sql @@ -9,7 +9,7 @@ INCLUDE PERFETTO MODULE common.slices; -CREATE PERFETTO VIEW internal_fcp_metrics AS +CREATE PERFETTO VIEW _fcp_metrics AS SELECT ts, dur, @@ -19,7 +19,7 @@ SELECT FROM process_slice WHERE name = 'PageLoadMetrics.NavigationToFirstContentfulPaint'; -CREATE PERFETTO FUNCTION internal_page_load_metrics(event_name STRING) +CREATE PERFETTO FUNCTION _page_load_metrics(event_name STRING) RETURNS TABLE( ts LONG, dur LONG, @@ -92,22 +92,22 @@ SELECT timing_interactive.ts AS mark_interactive_ts, fcp.url, fcp.browser_upid -FROM internal_fcp_metrics fcp +FROM _fcp_metrics fcp LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.NavigationToLargestContentfulPaint') lcp + _page_load_metrics('PageLoadMetrics.NavigationToLargestContentfulPaint') lcp USING (navigation_id, browser_upid) LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.NavigationToDOMContentLoadedEventFired') load_fired + _page_load_metrics('PageLoadMetrics.NavigationToDOMContentLoadedEventFired') load_fired USING (navigation_id, browser_upid) LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.NavigationToMainFrameOnLoad') start_load + _page_load_metrics('PageLoadMetrics.NavigationToMainFrameOnLoad') start_load USING (navigation_id, browser_upid) LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyLoaded') timing_loaded + _page_load_metrics('PageLoadMetrics.UserTimingMarkFullyLoaded') timing_loaded USING (navigation_id, browser_upid) LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.UserTimingMarkFullyVisible') timing_visible + _page_load_metrics('PageLoadMetrics.UserTimingMarkFullyVisible') timing_visible USING (navigation_id, browser_upid) LEFT JOIN - internal_page_load_metrics('PageLoadMetrics.UserTimingMarkInteractive') timing_interactive + _page_load_metrics('PageLoadMetrics.UserTimingMarkInteractive') timing_interactive USING (navigation_id, browser_upid); diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql index 78d3964d38..7cad6975b2 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_cause_utils.sql @@ -4,7 +4,7 @@ -- Function to retrieve the upid for a surfaceflinger, as these are attributed -- to the GPU but are recorded on a different data source (and track group). -CREATE PERFETTO FUNCTION internal_get_process_id_for_surfaceflinger() +CREATE PERFETTO FUNCTION _get_process_id_for_surfaceflinger() -- The process id for surfaceflinger. RETURNS INT AS SELECT @@ -15,7 +15,7 @@ LIMIT 1; -- Map a generic process type to a specific name or substring of a name that -- can be found in the trace process table. -CREATE PERFETTO TABLE internal_process_type_to_name ( +CREATE PERFETTO TABLE _process_type_to_name ( -- The process type: one of 'Browser' or 'GPU'. process_type STRING, -- The process name for Chrome traces. @@ -38,7 +38,7 @@ SELECT process_glob FROM process_names; -CREATE PERFETTO FUNCTION internal_get_process_name( +CREATE PERFETTO FUNCTION _get_process_name( -- The process type: one of 'Browser' or 'GPU'. type STRING ) @@ -46,11 +46,11 @@ CREATE PERFETTO FUNCTION internal_get_process_name( RETURNS STRING AS SELECT process_name -FROM internal_process_type_to_name +FROM _process_type_to_name WHERE process_type = $type LIMIT 1; -CREATE PERFETTO FUNCTION internal_get_process_glob( +CREATE PERFETTO FUNCTION _get_process_glob( -- The process type: one of 'Browser' or 'GPU'. type STRING ) @@ -58,7 +58,7 @@ CREATE PERFETTO FUNCTION internal_get_process_glob( RETURNS STRING AS SELECT process_glob -FROM internal_process_type_to_name +FROM _process_type_to_name WHERE process_type = $type LIMIT 1; @@ -67,8 +67,8 @@ LIMIT 1; -- Function to retrieve the chrome process ID for a specific process type. Does -- not retrieve the Renderer process, as this is determined when the -- EventLatency is known. See function --- internal_get_renderer_upid_for_event_latency below. -CREATE PERFETTO FUNCTION internal_get_process_id_by_type( +-- _get_renderer_upid_for_event_latency below. +CREATE PERFETTO FUNCTION _get_process_id_by_type( -- The process type: one of 'Browser' or 'GPU'. type STRING ) @@ -79,12 +79,12 @@ RETURNS TABLE ( SELECT upid FROM process -WHERE name = internal_get_process_name($type) - OR name GLOB internal_get_process_glob($type); +WHERE name = _get_process_name($type) + OR name GLOB _get_process_glob($type); -- Function to retrieve the chrome process ID that a given EventLatency slice -- occurred on. This is the Renderer process. -CREATE PERFETTO FUNCTION internal_get_renderer_upid_for_event_latency( +CREATE PERFETTO FUNCTION _get_renderer_upid_for_event_latency( -- The slice id for an EventLatency slice. id INT ) @@ -97,7 +97,7 @@ WHERE id = $id; -- Helper function to retrieve all of the upids for a given process, thread, -- or EventLatency. -CREATE PERFETTO FUNCTION internal_processes_by_type_for_event_latency( +CREATE PERFETTO FUNCTION _processes_by_type_for_event_latency( -- The process type that the thread is on: one of 'Browser', 'Renderer' or -- 'GPU'. type STRING, @@ -114,7 +114,7 @@ WITH all_upids AS ( $type AS process, $thread AS thread, $event_latency_id AS event_latency_id, - internal_get_renderer_upid_for_event_latency($event_latency_id) AS upid + _get_renderer_upid_for_event_latency($event_latency_id) AS upid WHERE $type = 'Renderer' UNION ALL -- surfaceflinger upids @@ -122,7 +122,7 @@ WITH all_upids AS ( $type AS process, $thread AS thread, $event_latency_id AS event_latency_id, - internal_get_process_id_for_surfaceflinger() AS upid + _get_process_id_for_surfaceflinger() AS upid WHERE $type = 'GPU' AND $thread = 'surfaceflinger' UNION ALL -- Generic Browser and GPU process upids @@ -131,7 +131,7 @@ WITH all_upids AS ( $thread AS thread, $event_latency_id AS event_latency_id, upid - FROM internal_get_process_id_by_type($type) + FROM _get_process_id_by_type($type) WHERE $type = 'Browser' OR ($type = 'GPU' AND $thread != 'surfaceflinger') ) @@ -162,7 +162,7 @@ WITH threads AS ( ( SELECT DISTINCT upid - FROM internal_processes_by_type_for_event_latency( + FROM _processes_by_type_for_event_latency( $process_type, $thread_name, $event_latency_id) diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql index 4b20b6b841..5d22239250 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_jank_v3.sql @@ -36,7 +36,7 @@ SELECT FROM slice WHERE name = "InputLatency::GestureScrollUpdate" AND dur != -1; -CREATE PERFETTO TABLE internal_non_coalesced_gesture_scrolls AS +CREATE PERFETTO TABLE _non_coalesced_gesture_scrolls AS SELECT id, ts, @@ -73,7 +73,7 @@ scroll_updates_with_coalesce_info as MATERIALIZED ( -- presented scroll update they have been coalesced into. ( SELECT id - FROM internal_non_coalesced_gesture_scrolls non_coalesced + FROM _non_coalesced_gesture_scrolls non_coalesced WHERE non_coalesced.ts <= scroll_update.ts ORDER BY ts DESC LIMIT 1 @@ -91,13 +91,13 @@ SELECT FROM scroll_updates_with_coalesce_info coalesce_info WHERE coalesce_info.coalesced_to_scroll_update_slice_id = - internal_non_coalesced_gesture_scrolls.id + _non_coalesced_gesture_scrolls.id ORDER BY ts DESC LIMIT 1 ) as last_coalesced_input_ts, scroll_update_id, scroll_id -FROM internal_non_coalesced_gesture_scrolls; +FROM _non_coalesced_gesture_scrolls; -- Associate every trace_id with it's perceived delta_y on the screen after -- prediction. @@ -305,15 +305,26 @@ SELECT LAG(event_latency_id, 1, -1) OVER (PARTITION BY scroll_id ORDER BY min_start_ts) AS prev_event_latency_id FROM chrome_merged_frame_view; --- Calculate |VSYNC_INTERVAL| as the lowest delay between frames larger than --- zero. --- TODO(b/286222128): Emit this data from Chrome instead of calculating it. +-- Calculate |VSYNC_INTERVAL| as the lowest vsync seen in the trace or the +-- minimum delay between frames larger than zero. +-- +-- TODO(~M130): Remove the lowest vsync since we should always have vsync_interval_ms. CREATE PERFETTO VIEW chrome_vsyncs( -- The lowest delay between frames larger than zero. vsync_interval INT ) AS +WITH + trace_vsyncs AS ( + SELECT EXTRACT_ARG(slice.arg_set_id, 'event_latency.vsync_interval_ms') AS vsync_interval_ms + FROM + slice JOIN chrome_frame_info_with_delay + ON chrome_frame_info_with_delay.event_latency_id = slice.id + WHERE EXTRACT_ARG(slice.arg_set_id, 'event_latency.vsync_interval_ms') > 0 + ) SELECT - MIN(delay_since_last_frame) AS vsync_interval + COALESCE( + (SELECT MIN(vsync_interval_ms) FROM trace_vsyncs), + MIN(delay_since_last_frame)) AS vsync_interval FROM chrome_frame_info_with_delay WHERE delay_since_last_frame > 0; @@ -493,4 +504,4 @@ SELECT AS scroll_jank_causes FROM chrome_janky_frames -GROUP BY scroll_id; \ No newline at end of file +GROUP BY scroll_id; diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql index 41ead9a1f2..8df09370b1 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/scroll_offsets.sql @@ -32,7 +32,7 @@ INCLUDE PERFETTO MODULE chrome.scroll_jank.scroll_jank_v3; -- Non-coalesced scroll update events and their timestamps. -CREATE PERFETTO VIEW internal_non_coalesced_scrolls AS +CREATE PERFETTO VIEW _non_coalesced_scrolls AS SELECT scroll_update_id, ts @@ -45,7 +45,7 @@ WHERE is_coalesced = False; -- this trace event, the deltas recorded represent the true (read "original") -- values that the Browser receives from Android, and the only processing is -- scaling and translation. -CREATE PERFETTO TABLE internal_scroll_deltas AS +CREATE PERFETTO TABLE _scroll_deltas AS SELECT EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id, EXTRACT_ARG(arg_set_id, 'scroll_deltas.original_delta_y') AS delta_y, @@ -53,25 +53,25 @@ SELECT FROM slice WHERE name = "TranslateAndScaleWebInputEvent"; --- Associate the raw (original) deltas (internal_scroll_deltas) with the +-- Associate the raw (original) deltas (_scroll_deltas) with the -- corresponding non-coalesced scroll updates --- (internal_non_coalesced_scroll_updates) to get the timestamp of the event +-- (_non_coalesced_scroll_updates) to get the timestamp of the event -- those deltas. This allows for ordering delta recordings to track them over -- time. -CREATE PERFETTO VIEW internal_non_coalesced_deltas AS +CREATE PERFETTO VIEW _non_coalesced_deltas AS SELECT scroll_update_id, ts, delta_y -FROM internal_non_coalesced_scrolls -INNER JOIN internal_scroll_deltas +FROM _non_coalesced_scrolls +INNER JOIN _scroll_deltas USING (scroll_update_id); -- Selecting information scroll update events that have been coalesced, -- including timestamp and the specific event (scroll update id) it was -- coalesced into. Recordings of deltas will need to be associated with the -- timestamp of the scroll update they were coalesced into. -CREATE PERFETTO TABLE internal_scroll_update_coalesce_info AS +CREATE PERFETTO TABLE _scroll_update_coalesce_info AS SELECT ts, EXTRACT_ARG(arg_set_id, 'scroll_deltas.coalesced_to_trace_id') AS coalesced_to_scroll_update_id, @@ -80,19 +80,19 @@ FROM slice WHERE name = "WebCoalescedInputEvent::CoalesceWith" AND coalesced_to_scroll_update_id IS NOT NULL; --- Associate the raw (original) deltas (internal_scroll_deltas) with the --- corresponding coalesced scroll updates (internal_scroll_update_coalesce_info) +-- Associate the raw (original) deltas (_scroll_deltas) with the +-- corresponding coalesced scroll updates (_scroll_update_coalesce_info) -- to get the timestamp of the event those deltas were coalesced into. This -- allows us to get the scaled coordinates for all of the input events -- (original input coordinates can't be used due to scaling). -CREATE PERFETTO VIEW internal_coalesced_deltas AS +CREATE PERFETTO VIEW _coalesced_deltas AS SELECT - internal_scroll_update_coalesce_info.coalesced_to_scroll_update_id AS scroll_update_id, + _scroll_update_coalesce_info.coalesced_to_scroll_update_id AS scroll_update_id, ts, - internal_scroll_deltas.delta_y AS delta_y, + _scroll_deltas.delta_y AS delta_y, TRUE AS is_coalesced -FROM internal_scroll_update_coalesce_info -LEFT JOIN internal_scroll_deltas +FROM _scroll_update_coalesce_info +LEFT JOIN _scroll_deltas USING (scroll_update_id); -- All of the presented frame scroll update ids. @@ -115,7 +115,7 @@ AND args.flat_key GLOB 'scroll_deltas.trace_ids_in_gpu_frame*';; -- When every GestureScrollUpdate event is processed, the offset set by the -- compositor is recorded. This offset is scaled to the device screen size, and -- can be used to calculate deltas. -CREATE PERFETTO VIEW internal_presented_frame_offsets AS +CREATE PERFETTO VIEW _presented_frame_offsets AS SELECT EXTRACT_ARG(arg_set_id, 'scroll_deltas.trace_id') AS scroll_update_id, EXTRACT_ARG(arg_set_id, 'scroll_deltas.visual_offset_y') AS visual_offset_y @@ -124,8 +124,8 @@ WHERE name = 'InputHandlerProxy::HandleGestureScrollUpdate_Result'; -- The raw coordinates and pixel offsets for all input events which were part of -- a scroll. This includes input events that were converted to scroll events --- which were presented (internal_non_coalesced_scrolls) and scroll events which --- were coalesced (internal_coalesced_deltas). +-- which were presented (_non_coalesced_scrolls) and scroll events which +-- were coalesced (_coalesced_deltas). CREATE PERFETTO TABLE chrome_scroll_input_offsets( -- Trace id associated with the scroll. scroll_update_id INT, @@ -143,14 +143,14 @@ WITH all_deltas AS ( scroll_update_id, ts, delta_y - FROM internal_non_coalesced_deltas + FROM _non_coalesced_deltas WHERE delta_y IS NOT NULL UNION SELECT scroll_update_id, ts, delta_y - FROM internal_coalesced_deltas + FROM _coalesced_deltas WHERE delta_y IS NOT NULL ORDER BY scroll_update_id, ts) SELECT @@ -165,23 +165,23 @@ FROM all_deltas; -- Calculate the total visual offset for all presented frames (non-coalesced -- scroll updates) that have raw deltas recorded. These visual offsets -- correspond with the inverse of the deltas for the presented frame. -CREATE PERFETTO VIEW internal_preprocessed_presented_frame_offsets AS +CREATE PERFETTO VIEW _preprocessed_presented_frame_offsets AS SELECT chrome_full_frame_view.scroll_update_id, chrome_full_frame_view.presentation_timestamp AS ts, chrome_deltas_presented_frame_scroll_update_ids.id, - internal_presented_frame_offsets.visual_offset_y - - LAG(internal_presented_frame_offsets.visual_offset_y) + _presented_frame_offsets.visual_offset_y - + LAG(_presented_frame_offsets.visual_offset_y) OVER (ORDER BY chrome_full_frame_view.presentation_timestamp) AS presented_frame_visual_offset_y FROM chrome_full_frame_view -LEFT JOIN internal_scroll_deltas +LEFT JOIN _scroll_deltas USING (scroll_update_id) LEFT JOIN chrome_deltas_presented_frame_scroll_update_ids USING (scroll_update_id) -LEFT JOIN internal_presented_frame_offsets +LEFT JOIN _presented_frame_offsets USING (scroll_update_id) -WHERE internal_scroll_deltas.delta_y IS NOT NULL; +WHERE _scroll_deltas.delta_y IS NOT NULL; -- The scrolling offsets for the actual (applied) scroll events. These are not -- necessarily inclusive of all user scroll events, rather those scroll events @@ -204,7 +204,7 @@ WITH all_deltas AS ( id, MAX(ts) AS ts, SUM(presented_frame_visual_offset_y) * -1 AS delta_y - FROM internal_preprocessed_presented_frame_offsets + FROM _preprocessed_presented_frame_offsets GROUP BY id ORDER BY ts) SELECT diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql index 64c5e00c23..74141e6c3e 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/scroll_jank/utils.sql @@ -15,9 +15,9 @@ -- (1ns) divided by maximum value in denominator, giving 1e-9. -- Function : function takes scroll ids of frames to verify it's from --- the same scroll, and makes sure the frame ts occured within the scroll +-- the same scroll, and makes sure the frame ts occurred within the scroll -- timestamp of the neighbour and computes whether the frame was janky or not. -CREATE PERFETTO FUNCTION internal_is_janky_frame(cur_gesture_id LONG, +CREATE PERFETTO FUNCTION _is_janky_frame(cur_gesture_id LONG, neighbour_gesture_id LONG, neighbour_ts LONG, cur_gesture_begin_ts LONG, @@ -45,7 +45,7 @@ SELECT -- -- Returns the jank budget in percentage (i.e. 0.75) of vsync interval -- percentage. -CREATE PERFETTO FUNCTION internal_jank_budget( +CREATE PERFETTO FUNCTION _jank_budget( cur_frame_exact FLOAT, prev_frame_exact FLOAT, next_frame_exact FLOAT diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql index e29811a152..79b820f88f 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/speedometer.sql @@ -33,7 +33,7 @@ -- @column suite_name Suite name -- @column test_name Test name -- @column mark_type Type of mark (start, sync-end, async-end) -CREATE PERFETTO VIEW internal_chrome_speedometer_mark +CREATE PERFETTO VIEW _chrome_speedometer_mark AS WITH speedometer_21_suite_name(suite_name) AS ( @@ -132,7 +132,7 @@ WITH COUNT() OVER (PARTITION BY iteration, suite_name, test_name ORDER BY ts ASC) AS mark_count - FROM internal_chrome_speedometer_mark + FROM _chrome_speedometer_mark JOIN slice USING (slice_id) ), diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/startups.sql b/naiveproxy/src/base/tracing/stdlib/chrome/startups.sql index 8d7e6407a0..f1e852bc4c 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/startups.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/startups.sql @@ -8,7 +8,7 @@ INCLUDE PERFETTO MODULE common.slices; -- If TimeToFirstVisibleContent is available, then this event will be the -- main event of the startup. Otherwise, the event for the start timestamp will -- be used. -CREATE PERFETTO VIEW internal_startup_start_events AS +CREATE PERFETTO VIEW _startup_start_events AS WITH starts AS ( SELECT @@ -60,7 +60,7 @@ FROM activity_ids -- Chrome launch causes, not recorded at start time; use the activity id to -- join with the actual startup events. -CREATE PERFETTO VIEW internal_launch_causes AS +CREATE PERFETTO VIEW _launch_causes AS SELECT EXTRACT_ARG(arg_set_id, 'startup.activity_id') AS activity_id, EXTRACT_ARG(arg_set_id, 'startup.launch_cause') AS launch_cause, @@ -93,6 +93,6 @@ SELECT start_events.first_visible_content_ts, launches.launch_cause, start_events.browser_upid -FROM internal_startup_start_events start_events - LEFT JOIN internal_launch_causes launches +FROM _startup_start_events start_events + LEFT JOIN _launch_causes launches USING(activity_id, browser_upid); diff --git a/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql b/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql index 0c7b18b1f5..420ef6bad6 100644 --- a/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql +++ b/naiveproxy/src/base/tracing/stdlib/chrome/tasks.sql @@ -8,7 +8,7 @@ INCLUDE PERFETTO MODULE common.slices; -- argument of descendant ScopedSetIpcHash slice. -- This is relevant only for the older Chrome traces, where mojo IPC -- hash was reported in a separate ScopedSetIpcHash slice. -CREATE PERFETTO FUNCTION internal_extract_mojo_ipc_hash(slice_id INT) +CREATE PERFETTO FUNCTION _extract_mojo_ipc_hash(slice_id INT) RETURNS INT AS SELECT EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.ipc_hash") FROM descendant_slice($slice_id) @@ -18,7 +18,7 @@ LIMIT 1; -- Returns the frame type (main frame vs subframe) for key navigation tasks -- which capture the associated RenderFrameHost in an argument. -CREATE PERFETTO FUNCTION internal_extract_frame_type(slice_id INT) +CREATE PERFETTO FUNCTION _extract_frame_type(slice_id INT) RETURNS INT AS SELECT EXTRACT_ARG(arg_set_id, "render_frame_host.frame_type") FROM descendant_slice($slice_id) @@ -31,7 +31,7 @@ WHERE name IN ( LIMIT 1; -- Human-readable aliases for a few key navigation tasks. -CREATE PERFETTO FUNCTION internal_human_readable_navigation_task_name( +CREATE PERFETTO FUNCTION _human_readable_navigation_task_name( task_name STRING) RETURNS STRING AS SELECT @@ -47,19 +47,19 @@ SELECT END; -- Takes a task name and formats it correctly for scheduler tasks. -CREATE PERFETTO FUNCTION internal_format_scheduler_task_name(task_name STRING) +CREATE PERFETTO FUNCTION _format_scheduler_task_name(task_name STRING) RETURNS STRING AS SELECT printf("RunTask(posted_from=%s)", $task_name); -- Takes the category and determines whether it is "Java" only, as opposed to -- "toplevel,Java". -CREATE PERFETTO FUNCTION internal_java_not_top_level_category(category STRING) +CREATE PERFETTO FUNCTION _java_not_top_level_category(category STRING) RETURNS BOOL AS SELECT $category GLOB "*Java*" AND $category not GLOB "*toplevel*"; -- Takes the category and determines whether is any valid -- toplevel category or combination of categories. -CREATE PERFETTO FUNCTION internal_any_top_level_category(category STRING) +CREATE PERFETTO FUNCTION _any_top_level_category(category STRING) RETURNS BOOL AS SELECT $category IN ("toplevel", "toplevel,viz", "toplevel,Java"); @@ -71,7 +71,7 @@ SELECT $category IN ("toplevel", "toplevel,viz", "toplevel,Java"); -- `CREATE PERFETTO TABLE`. -- Get task type for a given task kind. -CREATE PERFETTO FUNCTION internal_get_java_views_task_type(kind STRING) +CREATE PERFETTO FUNCTION _get_java_views_task_type(kind STRING) RETURNS STRING AS SELECT CASE $kind @@ -92,7 +92,7 @@ SELECT -- -- Note: this might include messages received within a sync mojo call. -- TODO(altimin): This should use EXTEND_TABLE when it becomes available. -CREATE TABLE internal_chrome_mojo_slices AS +CREATE TABLE _chrome_mojo_slices AS WITH -- Select all new-style (post crrev.com/c/3270337) mojo slices and -- generate |task_name| for them. @@ -119,7 +119,7 @@ new_mojo_slices AS ( old_associated_mojo_slices AS ( SELECT name AS interface_name, - internal_extract_mojo_ipc_hash(id) AS ipc_hash, + _extract_mojo_ipc_hash(id) AS ipc_hash, "message" AS message_type, id FROM slice @@ -134,7 +134,7 @@ old_non_associated_mojo_slices AS ( EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.watcher_notify_interface_tag"), EXTRACT_ARG(arg_set_id, "chrome_mojo_event_info.mojo_interface_tag") ) AS interface_name, - internal_extract_mojo_ipc_hash(id) AS ipc_hash, + _extract_mojo_ipc_hash(id) AS ipc_hash, "message" AS message_type, id FROM slice @@ -148,9 +148,9 @@ SELECT * FROM old_associated_mojo_slices UNION ALL SELECT * FROM old_non_associated_mojo_slices; --- As we lookup by ID on |internal_chrome_mojo_slices| table, add an index on +-- As we lookup by ID on |_chrome_mojo_slices| table, add an index on -- id to make lookups fast. -CREATE INDEX internal_chrome_mojo_slices_idx ON internal_chrome_mojo_slices(id); +CREATE INDEX _chrome_mojo_slices_idx ON _chrome_mojo_slices(id); -- This table contains a list of slices corresponding to the _representative_ -- Chrome Java view operations. @@ -165,7 +165,7 @@ CREATE INDEX internal_chrome_mojo_slices_idx ON internal_chrome_mojo_slices(id); -- capture toolbar screenshot. -- @column is_hardware_screenshot BOOL Whether this slice is a part of accelerated -- capture toolbar screenshot. -CREATE TABLE internal_chrome_java_views AS +CREATE TABLE _chrome_java_views AS WITH -- .draw, .onLayout and .onMeasure parts of the java view names don't add much, strip them. java_slices_with_trimmed_names AS ( @@ -190,7 +190,7 @@ java_slices_with_trimmed_names AS ( -- with either category = "toplevel" or category = "toplevel,Java". -- Also filter out the zero duration slices as an attempt to reduce noise as -- "Java" category contains misc events (as it's hard to add new categories). - WHERE internal_java_not_top_level_category(category) AND dur > 0 + WHERE _java_not_top_level_category(category) AND dur > 0 ), -- We filter out generic slices from various UI frameworks which don't tell us much about -- what exactly this view is doing. @@ -265,11 +265,11 @@ SELECT java_view.is_software_screenshot, java_view.is_hardware_screenshot, slice.id as slice_id -FROM internal_chrome_java_views java_view +FROM _chrome_java_views java_view JOIN slice USING (id); -- A list of Choreographer tasks (Android frame generation) in Chrome. -CREATE PERFETTO VIEW internal_chrome_choreographer_tasks +CREATE PERFETTO VIEW _chrome_choreographer_tasks AS SELECT id, @@ -281,7 +281,7 @@ FROM slice WHERE name GLOB "Looper.dispatch: android.view.Choreographer$FrameHandler*"; -- Extract task's posted_from information from task's arguments. -CREATE PERFETTO FUNCTION internal_get_posted_from(arg_set_id INT) +CREATE PERFETTO FUNCTION _get_posted_from(arg_set_id INT) RETURNS STRING AS WITH posted_from as ( SELECT @@ -303,7 +303,7 @@ FROM posted_from; -- @column kind The type of Java slice. -- @column ts The timestamp of the slice. -- @column name The name of the slice. -CREATE PERFETTO FUNCTION internal_select_begin_main_frame_java_slices( +CREATE PERFETTO FUNCTION _select_begin_main_frame_java_slices( name STRING) RETURNS TABLE(id INT, kind STRING, ts LONG, dur LONG, name STRING) AS SELECT @@ -315,7 +315,7 @@ SELECT FROM slice WHERE (name = $name - AND internal_get_posted_from(arg_set_id) = + AND _get_posted_from(arg_set_id) = "cc/trees/single_thread_proxy.cc:ScheduledActionSendBeginMainFrame"); -- A list of Chrome tasks which were performing operations with Java views, @@ -323,15 +323,15 @@ WHERE -- @column id INT Slice id. -- @column kind STRING Type of the task. -- @column java_views STRING Concatenated names of Java views used by the task. -CREATE PERFETTO VIEW internal_chrome_slices_with_java_views AS +CREATE PERFETTO VIEW _chrome_slices_with_java_views AS WITH -- Select UI thread BeginMainFrames (which are Chrome scheduler tasks) and -- Choreographer frames (which are looper tasks). root_slices AS ( SELECT id, kind - FROM INTERNAL_SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask') + FROM _SELECT_BEGIN_MAIN_FRAME_JAVA_SLICES('ThreadControllerImpl::RunTask') UNION ALL - SELECT id, kind FROM internal_chrome_choreographer_tasks + SELECT id, kind FROM _chrome_choreographer_tasks ), -- Intermediate step to allow us to sort java view names. root_slice_and_java_view_not_grouped AS ( @@ -339,7 +339,7 @@ WITH root.id, root.kind, java_view.name AS java_view_name FROM root_slices root JOIN descendant_slice(root.id) child - JOIN internal_chrome_java_views java_view ON java_view.id = child.id + JOIN _chrome_java_views java_view ON java_view.id = child.id ) SELECT root.id, @@ -350,7 +350,7 @@ LEFT JOIN root_slice_and_java_view_not_grouped java_view USING (id) GROUP BY root.id; -- A list of tasks executed by Chrome scheduler. -CREATE TABLE internal_chrome_scheduler_tasks AS +CREATE TABLE _chrome_scheduler_tasks AS SELECT id FROM slice @@ -399,8 +399,8 @@ CREATE PERFETTO VIEW chrome_scheduler_tasks( SELECT task.id, "chrome_scheduler_tasks" as type, - internal_format_scheduler_task_name( - internal_get_posted_from(slice.arg_set_id)) as name, + _format_scheduler_task_name( + _get_posted_from(slice.arg_set_id)) as name, slice.ts, slice.dur, thread.utid, @@ -414,8 +414,8 @@ SELECT slice.arg_set_id, slice.thread_ts, slice.thread_dur, - internal_get_posted_from(slice.arg_set_id) as posted_from -FROM internal_chrome_scheduler_tasks task + _get_posted_from(slice.arg_set_id) as posted_from +FROM _chrome_scheduler_tasks task JOIN slice using (id) JOIN thread_track ON slice.track_id = thread_track.id JOIN thread using (utid) @@ -424,7 +424,7 @@ ORDER BY task.id; -- Select the slice that might be the descendant mojo slice for the given task -- slice if it exists. -CREATE PERFETTO FUNCTION internal_get_descendant_mojo_slice_candidate( +CREATE PERFETTO FUNCTION _get_descendant_mojo_slice_candidate( slice_id INT ) RETURNS INT AS @@ -446,14 +446,14 @@ WHERE ORDER by depth, ts LIMIT 1; -CREATE PERFETTO FUNCTION internal_descendant_mojo_slice(slice_id INT) +CREATE PERFETTO FUNCTION _descendant_mojo_slice(slice_id INT) RETURNS TABLE(task_name STRING) AS SELECT printf("%s %s (hash=%d)", mojo.interface_name, mojo.message_type, mojo.ipc_hash) AS task_name FROM slice task -JOIN internal_chrome_mojo_slices mojo - ON mojo.id = internal_get_descendant_mojo_slice_candidate($slice_id) +JOIN _chrome_mojo_slices mojo + ON mojo.id = _get_descendant_mojo_slice_candidate($slice_id) WHERE task.id = $slice_id; -- A list of "Chrome tasks": top-level execution units (e.g. scheduler tasks / @@ -463,7 +463,7 @@ WHERE task.id = $slice_id; -- @column task_name STRING Name for the given task. -- @column task_type STRING Type of the task (e.g. "scheduler"). -- @column scheduling_delay INT -CREATE TABLE internal_chrome_tasks AS +CREATE TABLE _chrome_tasks AS WITH -- Select slices from "toplevel" category which do not have another -- "toplevel" slice as ancestor. The possible cases include sync mojo messages @@ -472,7 +472,7 @@ WITH non_embedded_toplevel_slices AS ( SELECT * FROM slice WHERE - internal_any_top_level_category(category) + _any_top_level_category(category) AND (SELECT count() FROM ancestor_slice(slice.id) anc WHERE anc.category GLOB "*toplevel*" or anc.category GLOB "*toplevel.viz*") = 0 ), @@ -488,7 +488,7 @@ non_embedded_java_slices AS ( "java" as task_type FROM slice s WHERE - internal_java_not_top_level_category(category) + _java_not_top_level_category(category) AND (SELECT count() FROM ancestor_slice(s.id) s2 WHERE s2.category GLOB "*toplevel*" OR s2.category GLOB "*Java*") = 0 @@ -498,8 +498,8 @@ java_views_tasks AS ( SELECT id, printf('%s(java_views=%s)', kind, java_views) AS task_name, - internal_get_java_views_task_type(kind) AS task_type - FROM internal_chrome_slices_with_java_views + _get_java_views_task_type(kind) AS task_type + FROM _chrome_slices_with_java_views ), scheduler_tasks AS ( SELECT @@ -521,7 +521,7 @@ scheduler_tasks_with_mojo AS ( "mojo" AS task_type FROM chrome_scheduler_tasks task - JOIN INTERNAL_DESCENDANT_MOJO_SLICE(task.id) receive_message + JOIN _DESCENDANT_MOJO_SLICE(task.id) receive_message WHERE task.posted_from IN ( "mojo/public/cpp/system/simple_watcher.cc:Notify", @@ -533,8 +533,8 @@ navigation_tasks AS ( WITH tasks_with_readable_names AS ( SELECT id, - internal_human_readable_navigation_task_name(task_name) as readable_name, - IFNULL(internal_extract_frame_type(id), 'unknown frame type') as frame_type + _human_readable_navigation_task_name(task_name) as readable_name, + IFNULL(_extract_frame_type(id), 'unknown frame type') as frame_type FROM scheduler_tasks_with_mojo ) @@ -627,7 +627,7 @@ SELECT s.thread_ts, s.thread_dur, cti.name as full_name -FROM internal_chrome_tasks cti +FROM _chrome_tasks cti JOIN slice s ON cti.id = s.id JOIN thread_track tt ON s.track_id = tt.id JOIN thread USING (utid) diff --git a/naiveproxy/src/base/types/is_complete.h b/naiveproxy/src/base/types/is_complete.h new file mode 100644 index 0000000000..54ed725378 --- /dev/null +++ b/naiveproxy/src/base/types/is_complete.h @@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_TYPES_IS_COMPLETE_H_ +#define BASE_TYPES_IS_COMPLETE_H_ + +#include + +namespace base { + +// True if `T` is completely defined. +template +concept IsComplete = requires { sizeof(T); } || + // Function types must be included explicitly since you + // cannot apply `sizeof()` to a function type. + std::is_function_v>; + +} // namespace base + +#endif // BASE_TYPES_IS_COMPLETE_H_ diff --git a/naiveproxy/src/base/types/pass_key.h b/naiveproxy/src/base/types/pass_key.h index e737b60d37..6684ffad2b 100644 --- a/naiveproxy/src/base/types/pass_key.h +++ b/naiveproxy/src/base/types/pass_key.h @@ -36,11 +36,19 @@ namespace base { // making the constructor unusable elsewhere. template class PassKey { - private: - // Avoid =default to disallow creation by uniform initialization. - PassKey() {} - friend T; + PassKey() = default; +}; + +// NonCopyablePassKey is a version of PassKey that also disallows copy/move +// construction/assignment. This way functions called with a passkey cannot use +// that key to invoke other passkey-protected functions. +template +class NonCopyablePassKey { + friend T; + NonCopyablePassKey() = default; + NonCopyablePassKey(const NonCopyablePassKey&) = delete; + NonCopyablePassKey& operator=(const NonCopyablePassKey&) = delete; }; } // namespace base diff --git a/naiveproxy/src/base/types/pass_key_nocompile.nc b/naiveproxy/src/base/types/pass_key_nocompile.nc index 65fd3250a5..2dd27ec046 100644 --- a/naiveproxy/src/base/types/pass_key_nocompile.nc +++ b/naiveproxy/src/base/types/pass_key_nocompile.nc @@ -7,6 +7,8 @@ #include "base/types/pass_key.h" +#include + namespace base { class Manager; @@ -14,15 +16,15 @@ class Manager; // May not be created without a PassKey. class Restricted { public: - Restricted(base::PassKey) {} + Restricted(PassKey) {} }; -void Secret(base::PassKey) {} +void Secret(PassKey) {} void CannotConstructFieldFromTemporaryPassKey() { class NotAManager { public: - NotAManager() : restricted_(base::PassKey()) {} // expected-error {{calling a private constructor of class 'base::PassKey'}} + NotAManager() : restricted_(PassKey()) {} // expected-error {{calling a private constructor of class 'base::PassKey'}} private: Restricted restricted_; @@ -40,7 +42,7 @@ void CannotConstructFieldFromImplicitPassKey() { } void CannotConstructTemporaryPassKey() { - Secret(base::PassKey()); // expected-error {{calling a private constructor of class 'base::PassKey'}} + Secret(PassKey()); // expected-error {{calling a private constructor of class 'base::PassKey'}} } void CannotConstructPassKeyImplicitly() { @@ -48,8 +50,16 @@ void CannotConstructPassKeyImplicitly() { } void CannotConstructNamedPassKey() { - base::PassKey key {}; // expected-error {{calling a private constructor of class 'base::PassKey'}} + PassKey key {}; // expected-error {{calling a private constructor of class 'base::PassKey'}} Secret(key); } +void CannotCopyNonCopyablePassKey(NonCopyablePassKey key) { + CannotCopyNonCopyablePassKey(key); // expected-error {{call to deleted constructor of 'NonCopyablePassKey'}} +} + +void CannotMoveNonCopyablePassKey(NonCopyablePassKey key) { + CannotMoveNonCopyablePassKey(std::move(key)); // expected-error {{call to deleted constructor of 'NonCopyablePassKey'}} +} + } // namespace base diff --git a/naiveproxy/src/base/unsafe_buffers_nocompile.nc b/naiveproxy/src/base/unsafe_buffers_nocompile.nc new file mode 100644 index 0000000000..f0e245b25f --- /dev/null +++ b/naiveproxy/src/base/unsafe_buffers_nocompile.nc @@ -0,0 +1,21 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This is a "No Compile Test" suite. +// http://dev.chromium.org/developers/testing/no-compile-tests + +#include "base/compiler_specific.h" + +namespace base { + +UNSAFE_BUFFER_USAGE int uses_pointer_as_array(int* i) { + return UNSAFE_BUFFERS(i[1]); +} + +void CallToUnsafeBufferFunctionDisallowed() { + int arr[] = {1, 2}; + uses_pointer_as_array(arr); // expected-error {{function introduces unsafe buffer manipulation}} +} + +} // namespace base diff --git a/naiveproxy/src/base/version_info/android/channel_getter.cc b/naiveproxy/src/base/version_info/android/channel_getter.cc index bd6c7ce8bb..d7b3c4a391 100644 --- a/naiveproxy/src/base/version_info/android/channel_getter.cc +++ b/naiveproxy/src/base/version_info/android/channel_getter.cc @@ -10,7 +10,7 @@ namespace version_info { namespace android { Channel GetChannel() { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); return static_cast(Java_VersionConstantsBridge_getChannel(env)); } diff --git a/naiveproxy/src/base/win/.clang-tidy b/naiveproxy/src/base/win/.clang-tidy index 3934a0eadf..c9ed66314c 100644 --- a/naiveproxy/src/base/win/.clang-tidy +++ b/naiveproxy/src/base/win/.clang-tidy @@ -7,6 +7,7 @@ Checks: '-*, google-build-namespaces, google-default-arguments, google-readability-namespace-comments, + google-upgrade-googletest-case, modernize-avoid-bind, modernize-concat-nested-namespaces, modernize-make-shared, diff --git a/naiveproxy/src/base/win/event_trace_consumer.h b/naiveproxy/src/base/win/event_trace_consumer.h index ed5c9dfe57..a3afeb458d 100644 --- a/naiveproxy/src/base/win/event_trace_consumer.h +++ b/naiveproxy/src/base/win/event_trace_consumer.h @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -20,9 +21,10 @@ namespace base { namespace win { // This class is a base class that makes it easier to consume events -// from realtime or file sessions. Concrete consumers need to subclass -// a specialization of this class and override the ProcessEvent and/or -// the ProcessBuffer methods to implement the event consumption logic. +// from realtime or file sessions. Concrete consumers need to subclass a +// specialization of this class and override the ProcessEvent, the +// ProcessEventRecord and/or the ProcessBuffer methods to implement the +// event consumption logic. // Usage might look like: // class MyConsumer: public EtwTraceConsumerBase { // protected: @@ -35,6 +37,16 @@ namespace win { template class EtwTraceConsumerBase { public: + // If true, receive events in the new EVENT_RECORD format. To receive + // events in the new format, ProcessEventRecord() must be overridden. + // See PROCESS_TRACE_MODE_EVENT_RECORD from + // https://learn.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-event_trace_logfilea + static constexpr bool kEnableRecordMode = false; + // If true, TimeStamps in EVENT_HEADER and EVENT_TRACE_HEADER are not + // converted to system time. See PROCESS_TRACE_MODE_RAW_TIMESTAMP from + // https://learn.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-event_trace_logfilea + static constexpr bool kRawTimestamp = false; + // Constructs a closed consumer. EtwTraceConsumerBase() = default; @@ -65,11 +77,15 @@ class EtwTraceConsumerBase { protected: // Override in subclasses to handle events. static void ProcessEvent(EVENT_TRACE* event) {} + // Override in subclasses to handle events. + static void ProcessEventRecord(EVENT_RECORD* event_record) {} // Override in subclasses to handle buffers. static bool ProcessBuffer(EVENT_TRACE_LOGFILE* buffer) { return true; // keep going } + HRESULT OpenSessionImpl(EVENT_TRACE_LOGFILE& logfile); + protected: // Currently open sessions. std::vector trace_handles_; @@ -79,6 +95,9 @@ class EtwTraceConsumerBase { static void WINAPI ProcessEventCallback(EVENT_TRACE* event) { ImplClass::ProcessEvent(event); } + static void WINAPI ProcessEventRecordCallback(EVENT_RECORD* event_record) { + ImplClass::ProcessEventRecord(event_record); + } static ULONG WINAPI ProcessBufferCallback(PEVENT_TRACE_LOGFILE buffer) { return ImplClass::ProcessBuffer(buffer); } @@ -87,27 +106,34 @@ class EtwTraceConsumerBase { template inline HRESULT EtwTraceConsumerBase::OpenRealtimeSession( const wchar_t* session_name) { - EVENT_TRACE_LOGFILE logfile = {}; - logfile.LoggerName = const_cast(session_name); - logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE; - logfile.BufferCallback = &ProcessBufferCallback; - logfile.EventCallback = &ProcessEventCallback; - logfile.Context = this; - TRACEHANDLE trace_handle = ::OpenTrace(&logfile); - if (reinterpret_cast(INVALID_HANDLE_VALUE) == trace_handle) - return HRESULT_FROM_WIN32(::GetLastError()); - - trace_handles_.push_back(trace_handle); - return S_OK; + EVENT_TRACE_LOGFILE logfile = { + .LoggerName = const_cast(session_name), + .ProcessTraceMode = PROCESS_TRACE_MODE_REAL_TIME, + }; + return OpenSessionImpl(logfile); } template inline HRESULT EtwTraceConsumerBase::OpenFileSession( const wchar_t* file_name) { - EVENT_TRACE_LOGFILE logfile = {}; - logfile.LogFileName = const_cast(file_name); + EVENT_TRACE_LOGFILE logfile = {.LogFileName = + const_cast(file_name)}; + return OpenSessionImpl(logfile); +} + +template +HRESULT EtwTraceConsumerBase::OpenSessionImpl( + EVENT_TRACE_LOGFILE& logfile) { + if (ImplClass::kEnableRecordMode) { + logfile.ProcessTraceMode |= PROCESS_TRACE_MODE_EVENT_RECORD; + logfile.EventRecordCallback = &ProcessEventRecordCallback; + } else { + logfile.EventCallback = &ProcessEventCallback; + } + if (ImplClass::kRawTimestamp) { + logfile.ProcessTraceMode |= PROCESS_TRACE_MODE_RAW_TIMESTAMP; + } logfile.BufferCallback = &ProcessBufferCallback; - logfile.EventCallback = &ProcessEventCallback; logfile.Context = this; TRACEHANDLE trace_handle = ::OpenTrace(&logfile); if (reinterpret_cast(INVALID_HANDLE_VALUE) == trace_handle) diff --git a/naiveproxy/src/base/win/i18n.cc b/naiveproxy/src/base/win/i18n.cc index bd2b851dce..5a75a62138 100644 --- a/naiveproxy/src/base/win/i18n.cc +++ b/naiveproxy/src/base/win/i18n.cc @@ -10,7 +10,7 @@ #include #include "base/check_op.h" -#include "base/strings/string_piece.h" + #include "base/strings/string_split.h" #include "base/strings/string_util.h" diff --git a/naiveproxy/src/base/win/iat_patch_function.cc b/naiveproxy/src/base/win/iat_patch_function.cc index f9de698044..827679de74 100644 --- a/naiveproxy/src/base/win/iat_patch_function.cc +++ b/naiveproxy/src/base/win/iat_patch_function.cc @@ -19,14 +19,9 @@ struct InterceptFunctionInformation { bool finished_operation; const char* imported_from_module; const char* function_name; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #reinterpret-cast-trivial-type + // RAW_PTR_EXCLUSION: #reinterpret-cast-trivial-type RAW_PTR_EXCLUSION void* new_function; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #reinterpret-cast-trivial-type RAW_PTR_EXCLUSION void** old_function; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #reinterpret-cast-trivial-type RAW_PTR_EXCLUSION IMAGE_THUNK_DATA** iat_thunk; DWORD return_code; }; @@ -217,9 +212,10 @@ DWORD IATPatchFunction::PatchFromModule(HMODULE module, DCHECK_EQ(nullptr, intercept_function_); DCHECK(module); - DWORD error = - InterceptImportedFunction(module, imported_from_module, function_name, - new_function, &original_function_, &iat_thunk_); + DWORD error = InterceptImportedFunction( + module, imported_from_module, function_name, new_function, + &original_function_.AsEphemeralRawAddr(), + &iat_thunk_.AsEphemeralRawAddr()); if (NO_ERROR == error) { DCHECK_NE(original_function_, intercept_function_); diff --git a/naiveproxy/src/base/win/iat_patch_function.h b/naiveproxy/src/base/win/iat_patch_function.h index 3f3502d558..fb4522d7db 100644 --- a/naiveproxy/src/base/win/iat_patch_function.h +++ b/naiveproxy/src/base/win/iat_patch_function.h @@ -9,7 +9,6 @@ #include "base/base_export.h" #include "base/memory/raw_ptr.h" -#include "base/memory/raw_ptr_exclusion.h" namespace base { namespace win { @@ -71,12 +70,8 @@ class BASE_EXPORT IATPatchFunction { private: HMODULE module_handle_ = nullptr; raw_ptr intercept_function_ = nullptr; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION void* original_function_ = nullptr; - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of - RAW_PTR_EXCLUSION IMAGE_THUNK_DATA* iat_thunk_ = nullptr; + raw_ptr original_function_ = nullptr; + raw_ptr iat_thunk_ = nullptr; }; } // namespace win diff --git a/naiveproxy/src/base/win/map.h b/naiveproxy/src/base/win/map.h index 88700c690c..1308629f19 100644 --- a/naiveproxy/src/base/win/map.h +++ b/naiveproxy/src/base/win/map.h @@ -13,7 +13,7 @@ #include "base/check_op.h" #include "base/containers/contains.h" -#include "base/notreached.h" +#include "base/notimplemented.h" #include "base/win/vector.h" #include "base/win/winrt_foundation_helpers.h" diff --git a/naiveproxy/src/base/win/scoped_co_mem.h b/naiveproxy/src/base/win/scoped_co_mem.h index 0667fbc7e2..9af9175786 100644 --- a/naiveproxy/src/base/win/scoped_co_mem.h +++ b/naiveproxy/src/base/win/scoped_co_mem.h @@ -55,8 +55,7 @@ class ScopedCoMem { T* get() const { return mem_ptr_; } private: - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #addr-of, #union + // RAW_PTR_EXCLUSION: #addr-of, #union RAW_PTR_EXCLUSION T* mem_ptr_; }; diff --git a/naiveproxy/src/base/win/scoped_hstring.cc b/naiveproxy/src/base/win/scoped_hstring.cc index 20e027e346..05a1cf4910 100644 --- a/naiveproxy/src/base/win/scoped_hstring.cc +++ b/naiveproxy/src/base/win/scoped_hstring.cc @@ -14,7 +14,7 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/process/memory.h" -#include "base/strings/string_piece.h" + #include "base/strings/utf_string_conversions.h" namespace base { @@ -53,7 +53,7 @@ ScopedHString ScopedHString::Create(std::wstring_view str) { } // static -ScopedHString ScopedHString::Create(StringPiece str) { +ScopedHString ScopedHString::Create(std::string_view str) { return Create(UTF8ToWide(str)); } diff --git a/naiveproxy/src/base/win/scoped_hstring.h b/naiveproxy/src/base/win/scoped_hstring.h index 50b8451663..753722838f 100644 --- a/naiveproxy/src/base/win/scoped_hstring.h +++ b/naiveproxy/src/base/win/scoped_hstring.h @@ -11,7 +11,6 @@ #include #include "base/scoped_generic.h" -#include "base/strings/string_piece.h" namespace base { @@ -47,10 +46,10 @@ class BASE_EXPORT ScopedHString explicit ScopedHString(HSTRING hstr); static ScopedHString Create(std::wstring_view str); - static ScopedHString Create(StringPiece str); + static ScopedHString Create(std::string_view str); // Returns a view into the memory buffer managed by the instance. The returned - // StringPiece is only valid during the lifetime of this ScopedHString + // std::string_view is only valid during the lifetime of this ScopedHString // instance. std::wstring_view Get() const; diff --git a/naiveproxy/src/base/win/security_descriptor.cc b/naiveproxy/src/base/win/security_descriptor.cc index 3d16ea4a45..0daf5db8f0 100644 --- a/naiveproxy/src/base/win/security_descriptor.cc +++ b/naiveproxy/src/base/win/security_descriptor.cc @@ -4,9 +4,12 @@ #include "base/win/security_descriptor.h" +// clang-format off +#include // Must be in front of other Windows header files. +// clang-format on + #include #include -#include #include #include diff --git a/naiveproxy/src/base/win/sid.cc b/naiveproxy/src/base/win/sid.cc index 0f1a2ec79a..3323cc7cbf 100644 --- a/naiveproxy/src/base/win/sid.cc +++ b/naiveproxy/src/base/win/sid.cc @@ -4,7 +4,9 @@ #include "base/win/sid.h" -#include +// clang-format off +#include // Must be in front of other Windows header files. +// clang-format on #include #include diff --git a/naiveproxy/src/base/win/windows_version.cc b/naiveproxy/src/base/win/windows_version.cc index 04bd7ae042..88cfcad5d4 100644 --- a/naiveproxy/src/base/win/windows_version.cc +++ b/naiveproxy/src/base/win/windows_version.cc @@ -349,6 +349,9 @@ Version OSInfo::MajorMinorBuildToVersion(uint32_t major, } if (major == 10) { + if (build >= 22631) { + return Version::WIN11_23H2; + } if (build >= 22621) { return Version::WIN11_22H2; } diff --git a/naiveproxy/src/base/win/windows_version.h b/naiveproxy/src/base/win/windows_version.h index 145ff47f77..1248047b5b 100644 --- a/naiveproxy/src/base/win/windows_version.h +++ b/naiveproxy/src/base/win/windows_version.h @@ -58,6 +58,7 @@ enum class Version { SERVER_2022 = 21, // Server 2022: Build 20348. WIN11 = 22, // Win11 21H2: Build 22000. WIN11_22H2 = 23, // Win11 22H2: Build 22621. + WIN11_23H2 = 24, // Win11 23H2: Build 22631. WIN_LAST, // Indicates error condition. }; diff --git a/naiveproxy/src/base/win/wmi.h b/naiveproxy/src/base/win/wmi.h index d918ede0de..065e880b1a 100644 --- a/naiveproxy/src/base/win/wmi.h +++ b/naiveproxy/src/base/win/wmi.h @@ -23,6 +23,7 @@ #include #include +#include #include #include "base/base_export.h" diff --git a/naiveproxy/src/build.sh b/naiveproxy/src/build.sh index 9c7cd5117e..8d6bea83f2 100755 --- a/naiveproxy/src/build.sh +++ b/naiveproxy/src/build.sh @@ -103,6 +103,13 @@ case "$EXTRA_FLAGS" in ;; esac +# See https://github.com/llvm/llvm-project/issues/86430 +if [ "$target_os" = "linux" -a "$target_cpu" = "x64" ]; then + flags="$flags"' + use_cfi_icall=false' +fi + + rm -rf "./$out" mkdir -p out diff --git a/naiveproxy/src/build/BUILD.gn b/naiveproxy/src/build/BUILD.gn index fc551fa19d..00bf4d8571 100644 --- a/naiveproxy/src/build/BUILD.gn +++ b/naiveproxy/src/build/BUILD.gn @@ -11,6 +11,10 @@ import("//build/config/features.gni") import("//build/util/process_version.gni") import("//build_overrides/build.gni") +if (is_ios) { + import("//build/config/ios/ios_sdk.gni") +} + source_set("buildflag_header_h") { sources = [ "buildflag.h" ] } @@ -84,6 +88,12 @@ buildflag_header("robolectric_buildflags") { flags = [ "IS_ROBOLECTRIC=$is_robolectric" ] } +buildflag_header("ios_buildflags") { + header = "ios_buildflags.h" + _is_ios_app_extension = is_ios && ios_is_app_extension + flags = [ "IS_IOS_APP_EXTENSION=$_is_ios_app_extension" ] +} + if (build_with_chromium) { group("gold_common_pytype") { testonly = true diff --git a/naiveproxy/src/build/android/docs/lint.md b/naiveproxy/src/build/android/docs/lint.md index ceb660dc92..04e42f7e1a 100644 --- a/naiveproxy/src/build/android/docs/lint.md +++ b/naiveproxy/src/build/android/docs/lint.md @@ -18,7 +18,6 @@ Chromium only runs lint on apk or bundle targets that explicitly set - `//chrome/android:monochrome_public_bundle` - `//android_webview/support_library/boundary_interfaces:boundary_interface_example_apk` - - `//remoting/android:remoting_apk` ## My code has a lint error diff --git a/naiveproxy/src/build/android/gyp/lint.py b/naiveproxy/src/build/android/gyp/lint.py index f3d85f78ec..75f9b598d2 100755 --- a/naiveproxy/src/build/android/gyp/lint.py +++ b/naiveproxy/src/build/android/gyp/lint.py @@ -28,6 +28,7 @@ _DISABLED_ALWAYS = [ "InflateParams", # Null is ok when inflating views for dialogs. "InlinedApi", # Constants are copied so they are always available. "LintBaseline", # Don't warn about using baseline.xml files. + "LintBaselineFixed", # We dont care if baseline.xml has unused entries. "MissingInflatedId", # False positives https://crbug.com/1394222 "MissingApplicationIcon", # False positive for non-production targets. "NetworkSecurityConfig", # Breaks on library certificates b/269783280. @@ -380,6 +381,11 @@ def _RunLint(custom_lint_jar_path, shutil.rmtree(resource_root_dir, ignore_errors=True) shutil.rmtree(srcjar_root_dir, ignore_errors=True) os.unlink(project_xml_path) + # lint-resources.xml is meant to be used for caching, but is suspected + # to lead to crashes: b/324598620 + lint_resources_xml = os.path.join(lint_gen_dir, 'lint-resources.xml') + if os.path.exists(lint_resources_xml): + os.unlink(lint_resources_xml) if failed: print('- For more help with lint in Chrome:', _LINT_MD_URL) diff --git a/naiveproxy/src/build/android/gyp/proguard.py b/naiveproxy/src/build/android/gyp/proguard.py index fbe02087c1..f5f4e8e11e 100755 --- a/naiveproxy/src/build/android/gyp/proguard.py +++ b/naiveproxy/src/build/android/gyp/proguard.py @@ -336,8 +336,7 @@ def _OptimizeWithR8(options, config_paths, libraries, dynamic_config_data): ] if options.uses_split: - # Provided by our CustomR8.java wrapper. - cmd += ['--enable-isolated-splits-asserts'] + cmd += ['--isolated-splits'] if options.disable_checks: cmd += ['--map-diagnostics:CheckDiscardDiagnostic', 'error', 'none'] diff --git a/naiveproxy/src/build/android/gyp/util/resource_utils.py b/naiveproxy/src/build/android/gyp/util/resource_utils.py index dac0ae7588..223c747baa 100644 --- a/naiveproxy/src/build/android/gyp/util/resource_utils.py +++ b/naiveproxy/src/build/android/gyp/util/resource_utils.py @@ -45,8 +45,8 @@ _ANDROID_TO_CHROMIUM_LANGUAGE_MAP = { ALL_RESOURCE_TYPES = { 'anim', 'animator', 'array', 'attr', 'bool', 'color', 'dimen', 'drawable', 'font', 'fraction', 'id', 'integer', 'interpolator', 'layout', 'macro', - 'menu', 'mipmap', 'plurals', 'raw', 'string', 'style', 'styleable', - 'transition', 'xml' + 'menu', 'mipmap', 'overlayable', 'plurals', 'raw', 'string', 'style', + 'styleable', 'transition', 'xml' } AAPT_IGNORE_PATTERN = ':'.join([ diff --git a/naiveproxy/src/build/android/gyp/util/resources_parser.py b/naiveproxy/src/build/android/gyp/util/resources_parser.py index 86d85407d3..ec3495f9e5 100644 --- a/naiveproxy/src/build/android/gyp/util/resources_parser.py +++ b/naiveproxy/src/build/android/gyp/util/resources_parser.py @@ -89,11 +89,8 @@ class RTxtGenerator: assert root.tag == 'resources' for child in root: - if child.tag == 'eat-comment': - # eat-comment is just a dummy documentation element. - continue - if child.tag == 'skip': - # skip is just a dummy element. + if child.tag in ('eat-comment', 'skip', 'overlayable', 'macro'): + # These tags do not create real resources continue if child.tag == 'declare-styleable': ret.update(self._ParseDeclareStyleable(child)) @@ -109,7 +106,7 @@ class RTxtGenerator: f'Infered resource type ({resource_type}) from xml entry ' f'({parsed_element}) (found in {xml_path}) is not listed in ' 'resource_utils.ALL_RESOURCE_TYPES. Teach resources_parser.py how ' - 'to parse this entry and/or add to the list.') + 'to parse this entry and then add to the list.') name = _ResourceNameToJavaSymbol(child.attrib['name']) ret.add(_TextSymbolEntry('int', resource_type, name, _DUMMY_RTXT_ID)) return ret diff --git a/naiveproxy/src/build/android/gyp/write_native_libraries_java.py b/naiveproxy/src/build/android/gyp/write_native_libraries_java.py index 96f084a032..28486e1a6e 100755 --- a/naiveproxy/src/build/android/gyp/write_native_libraries_java.py +++ b/naiveproxy/src/build/android/gyp/write_native_libraries_java.py @@ -73,10 +73,6 @@ def main(): required=True, default='CPU_FAMILY_UNKNOWN', help='CPU family.') - parser.add_argument( - '--main-component-library', - help='If used, the list of native libraries will only contain this ' - 'library. Dependencies are found in the library\'s "NEEDED" section.') parser.add_argument( '--output', required=True, help='Path to the generated srcjar file.') @@ -90,9 +86,7 @@ def main(): options = parser.parse_args(build_utils.ExpandFileArgs(sys.argv[1:])) native_libraries = [] - if options.main_component_library: - native_libraries.append(options.main_component_library) - elif options.native_libraries_list: + if options.native_libraries_list: with open(options.native_libraries_list) as f: native_libraries.extend(l.strip() for l in f) diff --git a/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py b/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py index 7d41f7e652..9da08d38e4 100644 --- a/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py +++ b/naiveproxy/src/build/android/pylib/gtest/gtest_test_instance.py @@ -398,6 +398,7 @@ class GtestTestInstance(test_instance.TestInstance): self._data_deps = [] self._gtest_filters = test_filter.InitializeFiltersFromArgs(args) self._run_disabled = args.run_disabled + self._run_pre_tests = args.run_pre_tests self._data_deps_delegate = data_deps_delegate self._runtime_deps_path = args.runtime_deps_path @@ -548,6 +549,10 @@ class GtestTestInstance(test_instance.TestInstance): def use_existing_test_data(self): return self._use_existing_test_data + @property + def run_pre_tests(self): + return self._run_pre_tests + #override def TestType(self): return 'gtest' @@ -614,11 +619,13 @@ class GtestTestInstance(test_instance.TestInstance): disabled_filter_items = [] if disabled_prefixes is None: - disabled_prefixes = ['FAILS_', 'PRE_'] + disabled_prefixes = ['FAILS_'] if '--run-manual' not in self._flags: disabled_prefixes += ['MANUAL_'] if not self._run_disabled: disabled_prefixes += ['DISABLED_', 'FLAKY_'] + if not self._run_pre_tests: + disabled_prefixes += ['PRE_'] disabled_filter_items += ['%s*' % dp for dp in disabled_prefixes] disabled_filter_items += ['*.%s*' % dp for dp in disabled_prefixes] diff --git a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py index b22c6a8448..3642610d6d 100644 --- a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance.py @@ -84,9 +84,6 @@ class TestListPickleException(test_exception.TestException): pass -# TODO(jbudorick): Make these private class methods of -# InstrumentationTestInstance once the instrumentation junit3_runner_class is -# deprecated. def ParseAmInstrumentRawOutput(raw_output): """Parses the output of an |am instrument -r| call. @@ -285,13 +282,12 @@ def FilterTests(tests, unique_test_name = GetUniqueTestName(test, sep='.') test_names.add(unique_test_name) - if test['is_junit4']: - junit4_test_name = GetTestNameWithoutParameterPostfix(test, sep='.') - test_names.add(junit4_test_name) + junit4_test_name = GetTestNameWithoutParameterSuffix(test, sep='.') + test_names.add(junit4_test_name) - unqualified_junit4_test_name = \ - GetTestNameWithoutParameterPostfix(unqualified_class_test, sep='.') - test_names.add(unqualified_junit4_test_name) + unqualified_junit4_test_name = GetTestNameWithoutParameterSuffix( + unqualified_class_test, sep='.') + test_names.add(unqualified_junit4_test_name) return test_names def get_tests_from_names(tests, test_names, tests_to_names): @@ -504,14 +500,6 @@ def SaveTestsToPickle(pickle_path, tests): pickle.dump(pickle_data, pickle_file) -class MissingJUnit4RunnerException(test_exception.TestException): - """Raised when JUnit4 runner is not provided or specified in apk manifest""" - - def __init__(self): - super().__init__( - 'JUnit4 runner is not provided or specified in test apk manifest.') - - def GetTestName(test, sep='#'): """Gets the name of the given test. @@ -531,9 +519,8 @@ def GetTestName(test, sep='#'): return test_name -def GetTestNameWithoutParameterPostfix( - test, sep='#', parameterization_sep='__'): - """Gets the name of the given JUnit4 test without parameter postfix. +def GetTestNameWithoutParameterSuffix(test, sep='#', parameterization_sep='__'): + """Gets the name of the given JUnit4 test without parameter suffix. For most WebView JUnit4 javatests, each test is parameterizatized with "__sandboxed_mode" to run in both non-sandboxed mode and sandboxed mode. @@ -544,10 +531,10 @@ def GetTestNameWithoutParameterPostfix( Args: test: the instrumentation test dict. sep: the character(s) that should join the class name and the method name. - parameterization_sep: the character(s) that seperate method name and method - parameterization postfix. + parameterization_sep: the character(s) that separate method name and method + parameterization suffix. Returns: - The test name without parameter postfix as a string. + The test name without parameter suffix as a string. """ name = GetTestName(test, sep=sep) return name.split(parameterization_sep)[0] @@ -597,7 +584,6 @@ class InstrumentationTestInstance(test_instance.TestInstance): self._test_apk_as_instant = False self._test_apk_incremental_install_json = None self._test_package = None - self._junit3_runner_class = None self._junit4_runner_class = None self._junit4_runner_supports_listing = None self._test_support_apk = None @@ -728,25 +714,12 @@ class InstrumentationTestInstance(test_instance.TestInstance): self._test_package = self._test_apk.GetPackageName() all_instrumentations = self._test_apk.GetAllInstrumentations() - all_junit3_runner_classes = [ - x for x in all_instrumentations if ('0xffffffff' in x.get( - 'chromium-junit3', ''))] - all_junit4_runner_classes = [ - x for x in all_instrumentations if ('0xffffffff' not in x.get( - 'chromium-junit3', ''))] - if len(all_junit3_runner_classes) > 1: - logging.warning('This test apk has more than one JUnit3 instrumentation') - if len(all_junit4_runner_classes) > 1: - logging.warning('This test apk has more than one JUnit4 instrumentation') + if len(all_instrumentations) > 1: + logging.warning('This test apk has more than one instrumentation') - self._junit3_runner_class = ( - all_junit3_runner_classes[0]['android:name'] - if all_junit3_runner_classes else self.test_apk.GetInstrumentationName()) - - self._junit4_runner_class = ( - all_junit4_runner_classes[0]['android:name'] - if all_junit4_runner_classes else None) + self._junit4_runner_class = (all_instrumentations[0]['android:name'] + if all_instrumentations else None) if self._junit4_runner_class: if self._test_apk_incremental_install_json: @@ -967,10 +940,6 @@ class InstrumentationTestInstance(test_instance.TestInstance): def is_unit_test(self): return self._is_unit_test - @property - def junit3_runner_class(self): - return self._junit3_runner_class - @property def junit4_runner_class(self): return self._junit4_runner_class @@ -1142,9 +1111,6 @@ class InstrumentationTestInstance(test_instance.TestInstance): def ProcessRawTests(self, raw_tests): inflated_tests = self._ParameterizeTestsWithFlags( self._InflateTests(raw_tests)) - if self._junit4_runner_class is None and any( - t['is_junit4'] for t in inflated_tests): - raise MissingJUnit4RunnerException() filtered_tests = FilterTests(inflated_tests, self._test_filters, self._annotations, self._excluded_annotations) if self._test_filters and not filtered_tests: @@ -1170,8 +1136,6 @@ class InstrumentationTestInstance(test_instance.TestInstance): 'class': c['class'], 'method': m['method'], 'annotations': a, - # TODO(https://crbug.com/1084729): Remove is_junit4. - 'is_junit4': True }) return inflated_tests diff --git a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance_test.py b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance_test.py index ea1eeed211..f58bfd4bbe 100755 --- a/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance_test.py +++ b/naiveproxy/src/build/android/pylib/instrumentation/instrumentation_test_instance_test.py @@ -130,7 +130,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): }, 'class': 'org.chromium.test.SampleTest', 'method': 'testMethod1', - 'is_junit4': True, }, { 'annotations': { @@ -139,7 +138,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): }, 'class': 'org.chromium.test.SampleTest', 'method': 'testMethod2', - 'is_junit4': True, }, { 'annotations': { @@ -148,7 +146,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): }, 'class': 'org.chromium.test.SampleTest2', 'method': 'testMethod1', - 'is_junit4': True, }, ] @@ -184,7 +181,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -248,7 +244,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -315,7 +310,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -357,7 +351,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -407,7 +400,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): }, 'class': 'org.chromium.test.SampleTest', 'method': 'testMethod1', - 'is_junit4': True, }, { 'annotations': { @@ -416,7 +408,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): }, 'class': 'org.chromium.test.SampleTest', 'method': 'testMethod1__sandboxed_mode', - 'is_junit4': True, }, ] @@ -464,7 +455,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest2', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -513,7 +503,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'MediumTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod2', }, { @@ -522,7 +511,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest2', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -571,7 +559,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, { @@ -580,7 +567,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest2', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -631,7 +617,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'MediumTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod2', }, ] @@ -724,7 +709,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'FlakyTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod2', }, ] @@ -785,7 +769,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'TestValue': '1', }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -834,7 +817,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest2', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -854,7 +836,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'timeout': '0'}, 'UiThreadTest': {}}, 'class': 'org.chromium.TestA', - 'is_junit4': True, 'method': 'testSimple'} unqualified_class_test = { 'class': test['class'].split('.')[-1], @@ -876,13 +857,12 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'UiThreadTest': {}}, 'class': 'org.chromium.TestA', 'flags': ['enable_features=abc'], - 'is_junit4': True, 'method': 'testSimple'} self.assertEqual( instrumentation_test_instance.GetUniqueTestName(test, sep='.'), 'org.chromium.TestA.testSimple_with_enable_features=abc') - def testGetTestNameWithoutParameterPostfix(self): + def testGetTestNameWithoutParameterSuffix(self): test = { 'annotations': { 'RunWith': {'value': 'class J4Runner'}, @@ -891,17 +871,16 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'UiThreadTest': {}}, 'class': 'org.chromium.TestA__sandbox_mode', 'flags': 'enable_features=abc', - 'is_junit4': True, 'method': 'testSimple'} unqualified_class_test = { 'class': test['class'].split('.')[-1], 'method': test['method'] } self.assertEqual( - instrumentation_test_instance.GetTestNameWithoutParameterPostfix( + instrumentation_test_instance.GetTestNameWithoutParameterSuffix( test, sep='.'), 'org.chromium.TestA') self.assertEqual( - instrumentation_test_instance.GetTestNameWithoutParameterPostfix( + instrumentation_test_instance.GetTestNameWithoutParameterSuffix( unqualified_class_test, sep='.'), 'TestA') def testGetTests_multipleAnnotationValuesRequested(self): @@ -947,7 +926,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'MediumTest': None, }, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod2', }, { @@ -958,7 +936,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'SmallTest': None, }, 'class': 'org.chromium.test.SampleTest2', - 'is_junit4': True, 'method': 'testMethod1', }, ] @@ -1133,26 +1110,22 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'annotations': {}, 'class': 'org.chromium.test.SampleTest', 'flags': ['--enable-features=abc', '--enable-features=def'], - 'is_junit4': True, 'method': 'testMethod1' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', 'flags': ['--enable-features=ghi', '--enable-features=jkl'], - 'is_junit4': True, 'method': 'testMethod2' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod3' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod4' }, ] @@ -1239,26 +1212,22 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'class': 'org.chromium.test.SampleTest', 'flags': ['--enable-features=abc', '--force-fieldtrials=trial/group'], - 'is_junit4': True, 'method': 'testMethod1' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', 'flags': ['--enable-features=def'], - 'is_junit4': True, 'method': 'testMethod2' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod3' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', - 'is_junit4': True, 'method': 'testMethod4' }, { @@ -1269,8 +1238,6 @@ class InstrumentationTestInstanceTest(unittest.TestCase): '--enable-features=abc2', '--force-fieldtrials=trial/group2', ], - 'is_junit4': - True, 'method': 'testMethod1' }, @@ -1328,14 +1295,12 @@ class InstrumentationTestInstanceTest(unittest.TestCase): 'annotations': {}, 'class': 'org.chromium.test.SampleTest', 'flags': ['--a1', '--a2'], - 'is_junit4': True, 'method': 'testMethod2' }, { 'annotations': {}, 'class': 'org.chromium.test.SampleTest', 'flags': ['--b1', '--b2'], - 'is_junit4': True, 'method': 'testMethod3' }, ] diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py index 9f1cdc2601..1fe1b240c3 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run.py @@ -155,6 +155,32 @@ def _GetLLVMProfilePath(device_coverage_dir, suite, coverage_index): str(coverage_index), '%2m%c.profraw'])) +def _GroupPreTests(tests): + pre_tests = dict() + other_tests = [] + for test in tests: + test_name_start = max(test.find('.') + 1, 0) + test_name = test[test_name_start:] + if test_name_start > 0 and test_name.startswith(_GTEST_PRETEST_PREFIX): + test_suite = test[:test_name_start - 1] + trim_test = test + trim_tests = [test] + + while test_name.startswith(_GTEST_PRETEST_PREFIX): + test_name = test_name[len(_GTEST_PRETEST_PREFIX):] + trim_test = '%s.%s' % (test_suite, test_name) + trim_tests.append(trim_test) + + # The trim test should exist at first place. For example, if a test has + # been disabled, there is no need to run PRE_ test with this test. + if trim_test in tests and (not trim_test in pre_tests or len( + pre_tests[trim_test]) < len(trim_tests)): + pre_tests[trim_test] = trim_tests + else: + other_tests.append(test) + return pre_tests, other_tests + + class _ApkDelegate: def __init__(self, test_instance, env): self._activity = test_instance.activity @@ -535,10 +561,6 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): # Delete suspect testcase from tests. tests = [test for test in tests if not test in self._crashes] - # Sort tests by hash. - # TODO(crbug.com/1257820): Add sorting logic back to _PartitionTests. - tests = self._SortTests(tests) - max_shard_size = self._test_instance.test_launcher_batch_limit shards.extend(self._PartitionTests(tests, device_count, max_shard_size)) @@ -612,28 +634,36 @@ class LocalDeviceGtestRun(local_device_test_run.LocalDeviceTestRun): return tests #override - def _GroupTests(self, tests): - pre_tests = dict() - other_tests = [] - for test in tests: - test_name_start = max(test.find('.') + 1, 0) - test_name = test[test_name_start:] - if test_name_start == 0 or not test_name.startswith( + def _AppendPreTestsForRetry(self, failed_tests, tests): + if not self._test_instance.run_pre_tests: + return failed_tests + + pre_tests, _ = _GroupPreTests(tests) + trim_failed_tests = set() + for failed_test in failed_tests: + failed_test_name_start = max(failed_test.find('.') + 1, 0) + failed_test_name = failed_test[failed_test_name_start:] + + if failed_test_name_start > 0 and failed_test_name.startswith( _GTEST_PRETEST_PREFIX): - other_tests.append(test) - else: - test_suite = test[:test_name_start - 1] - trim_test = test - trim_tests = [test] + failed_test_suite = failed_test[:failed_test_name_start - 1] + while failed_test_name.startswith(_GTEST_PRETEST_PREFIX): + failed_test_name = failed_test_name[len(_GTEST_PRETEST_PREFIX):] + failed_test = '%s.%s' % (failed_test_suite, failed_test_name) + trim_failed_tests.add(failed_test) - while test_name.startswith(_GTEST_PRETEST_PREFIX): - test_name = test_name[len(_GTEST_PRETEST_PREFIX):] - trim_test = '%s.%s' % (test_suite, test_name) - trim_tests.append(trim_test) + all_tests = [] + for trim_failed_test in trim_failed_tests: + if trim_failed_test in tests: + if trim_failed_test in pre_tests: + all_tests.extend(pre_tests[trim_failed_test]) + else: + all_tests.append(trim_failed_test) + return all_tests - if not trim_test in pre_tests or len( - pre_tests[trim_test]) < len(trim_tests): - pre_tests[trim_test] = trim_tests + #override + def _GroupTests(self, tests): + pre_tests, other_tests = _GroupPreTests(tests) all_tests = [] for other_test in other_tests: diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run_test.py b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run_test.py index ad67793034..777dc5b220 100755 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run_test.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_gtest_run_test.py @@ -84,6 +84,46 @@ class LocalDeviceGtestRunTest(unittest.TestCase): self.assertTrue(isSliceInList(expectedTestcase2, actualTestCase)) self.assertTrue(isSliceInList(expectedOtherTestcase, actualTestCase)) + def testAppendPreTests(self): + failed_tests = [ + "TestClass1.PRE_PRE_testcase1", + "TestClass1.abc_testcase2", + "TestClass1.PRE_def_testcase3", + "TestClass1.otherTestCase", + ] + tests = [ + "TestClass1.testcase1", + "TestClass1.otherTestCase", + "TestClass1.def_testcase3", + "TestClass1.PRE_testcase1", + "TestClass1.abc_testcase2", + "TestClass1.PRE_PRE_testcase1", + "TestClass1.PRE_abc_testcase2", + "TestClass1.PRE_def_testcase3", + "TestClass1.PRE_PRE_abc_testcase2", + ] + expectedTestcase1 = [ + "TestClass1.PRE_PRE_testcase1", + "TestClass1.PRE_testcase1", + "TestClass1.testcase1", + ] + expectedTestcase2 = [ + "TestClass1.PRE_PRE_abc_testcase2", + "TestClass1.PRE_abc_testcase2", + "TestClass1.abc_testcase2", + ] + expectedTestcase3 = [ + "TestClass1.PRE_def_testcase3", + "TestClass1.def_testcase3", + ] + expectedOtherTestcase = [ + "TestClass1.otherTestCase", + ] + actualTestCase = self._obj._AppendPreTestsForRetry(failed_tests, tests) + self.assertTrue(isSliceInList(expectedTestcase1, actualTestCase)) + self.assertTrue(isSliceInList(expectedTestcase2, actualTestCase)) + self.assertTrue(isSliceInList(expectedTestcase3, actualTestCase)) + self.assertTrue(isSliceInList(expectedOtherTestcase, actualTestCase)) if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py index e9a16f2914..c7ad9f9be0 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run.py @@ -861,7 +861,6 @@ class LocalDeviceInstrumentationTestRun( timeout = min(MAX_BATCH_TEST_TIMEOUT, FIXED_TEST_TIMEOUT_OVERHEAD + sum(timeouts)) else: - assert test['is_junit4'] test_name = instrumentation_test_instance.GetTestName(test) test_display_name = self._GetUniqueTestName(test) @@ -1795,7 +1794,7 @@ def _SetLinkOnResults(results, full_test_name, link_name, link): full_test_name: A string containing the full name of the test, e.g. org.chromium.chrome.SomeTestClass#someTestMethod. link_name: A string containing the name of the link being set. - link: A string containing the lkink being set. + link: A string containing the link being set. """ found_matching_test = _MatchingTestInResults(results, full_test_name) if not found_matching_test and _ShouldReportNoMatchingResult(full_test_name): diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py index acf25a0588..3bf149270a 100755 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_instrumentation_test_run_test.py @@ -34,7 +34,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): 'annotations': {}, 'class': 'SadTest', 'method': 'testFailure', - 'is_junit4': True, } result = base_test_result.BaseTestResult( 'SadTest.testFailure', base_test_result.ResultType.FAIL) @@ -45,7 +44,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): 'annotations': {'RetryOnFailure': None}, 'class': 'SadTest', 'method': 'testRetryOnFailure', - 'is_junit4': True, } result = base_test_result.BaseTestResult( 'SadTest.testRetryOnFailure', base_test_result.ResultType.FAIL) @@ -56,7 +54,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): 'annotations': {}, 'class': 'SadTest', 'method': 'testNotRun', - 'is_junit4': True, } result = base_test_result.BaseTestResult( 'SadTest.testNotRun', base_test_result.ResultType.NOTRUN) @@ -71,7 +68,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'WPRDummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertTrue( local_device_instrumentation_test_run._IsWPRRecordReplayTest(test)) @@ -85,7 +81,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'WPRDummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertFalse( local_device_instrumentation_test_run._IsWPRRecordReplayTest(test)) @@ -99,7 +94,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'WPRDummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertEqual( local_device_instrumentation_test_run._GetWPRArchivePath(test), 'abc') @@ -113,7 +107,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'WPRDummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertFalse( local_device_instrumentation_test_run._GetWPRArchivePath(test)) @@ -127,7 +120,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'DummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertTrue(local_device_instrumentation_test_run._IsRenderTest(test)) @@ -140,7 +132,6 @@ class LocalDeviceInstrumentationTestRunTest(unittest.TestCase): }, 'class': 'DummyTest', 'method': 'testRun', - 'is_junit4': True, } self.assertFalse(local_device_instrumentation_test_run._IsRenderTest(test)) diff --git a/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py b/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py index 2cff3e6082..da123ff1f1 100644 --- a/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py +++ b/naiveproxy/src/build/android/pylib/local/device/local_device_test_run.py @@ -162,6 +162,7 @@ class LocalDeviceTestRun(test_run.TestRun): self._env.ResetCurrentTry() while self._env.current_try < self._env.max_tries and tests: tries = self._env.current_try + tests = self._SortTests(tests) grouped_tests = self._GroupTests(tests) logging.info('STARTING TRY #%d/%d', tries + 1, self._env.max_tries) if tries > 0 and self._env.recover_devices: @@ -253,7 +254,10 @@ class LocalDeviceTestRun(test_run.TestRun): for test, result in tests_and_results.values() if is_failure_result(result)) - return [t for t, r in failed_tests_and_results if self._ShouldRetry(t, r)] + failed_tests = [ + t for t, r in failed_tests_and_results if self._ShouldRetry(t, r) + ] + return self._AppendPreTestsForRetry(failed_tests, tests) def _ApplyExternalSharding(self, tests, shard_index, total_shards): logging.info('Using external sharding settings. This is shard %d/%d', @@ -323,6 +327,11 @@ class LocalDeviceTestRun(test_run.TestRun): # if the size of the test group is larger than the max partition size on # its own, just put the group in its own shard instead of splitting up the # group. + # TODO(crbug/1257820): Add logic to support PRE_ test recognition but it + # may hurt performance in most scenarios. Currently all PRE_ tests are + # partitioned into the last shard. Unless the number of PRE_ tests are + # larger than the partition size, the PRE_ test may get assigned into a + # different shard and cause test failure. if (last_partition_size + test_count > partition_size and last_partition_size > 0): num_desired_partitions -= 1 @@ -388,6 +397,10 @@ class LocalDeviceTestRun(test_run.TestRun): # pylint: disable=no-self-use return tests + def _AppendPreTestsForRetry(self, failed_tests, tests): + # pylint: disable=no-self-use,unused-argument + return failed_tests + def _RunTest(self, device, test): raise NotImplementedError diff --git a/naiveproxy/src/build/android/pylib/local/machine/local_machine_hostside_test_run.py b/naiveproxy/src/build/android/pylib/local/machine/local_machine_hostside_test_run.py index e096fe126b..e2d38cbdba 100644 --- a/naiveproxy/src/build/android/pylib/local/machine/local_machine_hostside_test_run.py +++ b/naiveproxy/src/build/android/pylib/local/machine/local_machine_hostside_test_run.py @@ -2,18 +2,24 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import collections +import contextlib import dataclasses import json +import logging import os import re import sys +import time from typing import Optional +from devil.android import logcat_monitor from devil.android.tools import script_common from devil.android.tools import webview_app from pylib.base import base_test_result from pylib.base import test_run from pylib.local.machine import local_machine_junit_test_run as junitrun +from pylib.symbols import stack_symbolizer _FAILURE_TYPES = ( @@ -27,6 +33,12 @@ _TEST_END_RE = re.compile(r'.*=+ (\S+) ENDED: .*=+') _JSON_RESULTS_RE = re.compile( r'.*D/LUCIResultReporter: JSON result for LUCI: (.*\.json)\b') +LOGCAT_FILTERS = [ + 'chromium:v', + 'cr_*:v', + 'DEBUG:I', + 'StrictMode:D', +] @dataclasses.dataclass class _Job: @@ -40,6 +52,8 @@ class LocalMachineHostsideTestRun(test_run.TestRun): def __init__(self, env, test_instance): super().__init__(env, test_instance) self.webview_context = None + self.device = None + self.test_name_to_logcat = collections.defaultdict(collections.deque) # override def TestPackage(self): @@ -52,13 +66,13 @@ class LocalMachineHostsideTestRun(test_run.TestRun): # override def SetUp(self): if self._test_instance.use_webview_provider: - device = script_common.GetDevices( + self.device = script_common.GetDevices( requested_devices=None, denylist_file=None)[0] for apk in self._test_instance.additional_apks: - device.Install(apk) + self.device.Install(apk) self.webview_context = webview_app.UseWebViewProvider( - device, + self.device, self._test_instance.use_webview_provider) # Pylint is not smart enough to realize that this field has # an __enter__ method, and will complain loudly. @@ -116,6 +130,7 @@ class LocalMachineHostsideTestRun(test_run.TestRun): log_lines = [] current_test = None json_results_path = None + archive_logcat = None for line in junitrun.RunCommandsAndSerializeOutput([job], 1): if raw_logs_fh: raw_logs_fh.write(line) @@ -127,15 +142,31 @@ class LocalMachineHostsideTestRun(test_run.TestRun): if test_start_match := _TEST_START_RE.match(line): current_test = test_start_match.group(1) log_lines = [line] + if archive_logcat is not None: + archive_logcat.__exit__(None, None, None) + archive_logcat = self._ArchiveLogcat(self.device, current_test) + # Pylint is not smart enough to realize that this field has + # an __enter__ method, and will complain loudly. + # pylint: disable=no-member + archive_logcat.__enter__() + # pylint: enable=no-member else: log_lines.append(line) if _TEST_END_RE.match(line) and current_test: per_test_logs[current_test] = ''.join(log_lines) + archive_logcat.__exit__(None, None, None) + archive_logcat = None current_test = None elif json_results_path_match := _JSON_RESULTS_RE.match(line): json_results_path = json_results_path_match.group(1) sys.stdout.flush() + if archive_logcat is not None: + # Pylint is not smart enough to realize that this field has + # an __exit__ method, and will complain loudly. + # pylint: disable=no-member + archive_logcat.__exit__(None, None, None) + # pylint: enable=no-member result_list = [] if json_results_path: @@ -145,6 +176,16 @@ class LocalMachineHostsideTestRun(test_run.TestRun): for r in parsed_results: if r.GetType() in _FAILURE_TYPES: r.SetLog(per_test_logs.get(r.GetName(), '')) + attempt_counter = collections.Counter( + result.GetName() for result in parsed_results + ) + for result in parsed_results: + test_name = result.GetName() + logcat_deque = self.test_name_to_logcat[test_name] + if attempt_counter[test_name] == len(logcat_deque): + # Set logcat link in FIFO order in case of multiple test attempts + result.SetLink('logcat', logcat_deque.popleft()) + attempt_counter[test_name] -= 1 result_list += parsed_results else: @@ -169,6 +210,32 @@ class LocalMachineHostsideTestRun(test_run.TestRun): self.webview_context.__exit__(*sys.exc_info()) # pylint: enable=no-member + @contextlib.contextmanager + def _ArchiveLogcat(self, device, test_name): + stream_name = 'logcat_%s_shard%s_%s_%s' % ( + test_name.replace('#', '.'), 0, + time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) + + logcat_file = None + logmon = None + try: + with self._env.output_manager.ArchivedTempfile(stream_name, + 'logcat') as logcat_file: + symbolizer = stack_symbolizer.PassThroughSymbolizerPool( + device.product_cpu_abi) + with symbolizer: + with logcat_monitor.LogcatMonitor( + device.adb, + filter_specs=LOGCAT_FILTERS, + output_file=logcat_file.name, + check_error=False) as logmon: + yield logcat_file + finally: + if logmon: + logmon.Close() + if logcat_file and logcat_file.Link(): + logging.critical('Logcat saved to %s', logcat_file.Link()) + self.test_name_to_logcat[test_name].append(logcat_file.Link()) def _ParseResultsFromJson(json_results): result_list = [] diff --git a/naiveproxy/src/build/android/test_runner.py b/naiveproxy/src/build/android/test_runner.py index 29798b3a4a..94f1bbd46c 100755 --- a/naiveproxy/src/build/android/test_runner.py +++ b/naiveproxy/src/build/android/test_runner.py @@ -469,6 +469,12 @@ def AddGTestOptions(parser): help='Do not push new files to the device, instead using existing APK ' 'and test data. Only use when running the same test for multiple ' 'iterations.') + # This is currently only implemented for gtests tests. + parser.add_argument('--gtest_also_run_pre_tests', + '--gtest-also-run-pre-tests', + dest='run_pre_tests', + action='store_true', + help='Also run PRE_ tests if applicable.') def AddInstrumentationTestOptions(parser): diff --git a/naiveproxy/src/build/android/unused_resources/UnusedResources.java b/naiveproxy/src/build/android/unused_resources/UnusedResources.java index 079fa96023..bf20946a74 100644 --- a/naiveproxy/src/build/android/unused_resources/UnusedResources.java +++ b/naiveproxy/src/build/android/unused_resources/UnusedResources.java @@ -23,6 +23,7 @@ package build.android.unused_resources; import static com.android.ide.common.symbols.SymbolIo.readFromAapt; import static com.android.utils.SdkUtils.endsWithIgnoreCase; + import static com.google.common.base.Charsets.UTF_8; import com.android.ide.common.resources.usage.ResourceUsageModel; @@ -39,6 +40,7 @@ import com.android.tools.r8.ResourceShrinker.Command; import com.android.tools.r8.ResourceShrinker.ReferenceChecker; import com.android.tools.r8.origin.PathOrigin; import com.android.utils.XmlUtils; + import com.google.common.base.Charsets; import com.google.common.collect.Maps; import com.google.common.io.ByteStreams; @@ -194,6 +196,11 @@ public class UnusedResources { StringBuilder sb = new StringBuilder(); Collections.sort(mUnused); for (Resource resource : mUnused) { + if (resource.type.isSynthetic()) { + // Ignore synthetic resources like overlayable or macro that are + // not actually listed in the ResourceTable. + continue; + } sb.append(resource.type + "/" + resource.name + "#remove\n"); } Files.asCharSink(destinationFile, UTF_8).write(sb.toString()); @@ -205,6 +212,12 @@ public class UnusedResources { } } + private void dumpModel() { + if (mDebugPrinter != null) { + mDebugPrinter.print(mModel.dumpResourceModel()); + } + } + private void recordResources(Iterable resources) throws IOException, SAXException, ParserConfigurationException { for (File resDir : resources) { @@ -300,7 +313,8 @@ public class UnusedResources { || line.startsWith("android.support.v7.widget.ResourcesWrapper ") || (mResourcesWrapper == null // Recently wrapper moved && line.startsWith( - "android.support.v7.widget.TintContextWrapper$TintResources "))) { + "android.support.v7.widget.TintContextWrapper$TintResources" + + " "))) { mResourcesWrapper = line.substring(line.indexOf(arrowString) + arrowString.length(), line.indexOf(':') != -1 ? line.indexOf(':') : line.length()) diff --git a/naiveproxy/src/build/apple/OWNERS b/naiveproxy/src/build/apple/OWNERS index 07d900ebed..a54e2224e6 100644 --- a/naiveproxy/src/build/apple/OWNERS +++ b/naiveproxy/src/build/apple/OWNERS @@ -1,4 +1,3 @@ mark@chromium.org rohitrao@chromium.org -rsesek@chromium.org sdefresne@chromium.org diff --git a/naiveproxy/src/build/config/BUILDCONFIG.gn b/naiveproxy/src/build/config/BUILDCONFIG.gn index 8efbfc5500..881367826d 100644 --- a/naiveproxy/src/build/config/BUILDCONFIG.gn +++ b/naiveproxy/src/build/config/BUILDCONFIG.gn @@ -574,8 +574,6 @@ foreach(_target_type, if (defined(output_extension)) { _shlib_extension = ".$output_extension" - } else if (is_component_build && _target_type != "loadable_module") { - _shlib_extension = ".cr.so" } else { _shlib_extension = ".so" } @@ -632,6 +630,11 @@ template("component") { if (defined(_output_name)) { output_name = _output_name } + if (is_component_build && is_android) { + # By appending .cr, we prevent name collisions with libraries already + # loaded by the Android zygote. + output_extension = "cr.so" + } forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) } diff --git a/naiveproxy/src/build/config/android/config.gni b/naiveproxy/src/build/config/android/config.gni index 1b8352cdef..ae6136cf51 100644 --- a/naiveproxy/src/build/config/android/config.gni +++ b/naiveproxy/src/build/config/android/config.gni @@ -392,9 +392,40 @@ if (is_android || is_chromeos) { android_sdk_tools_bundle_aapt2 = "${android_sdk_tools_bundle_aapt2_dir}/aapt2" - # Actions that use java should add this as an input so that they are rebuilt + _common_inputs_for_jre_jdk = [ + "//third_party/jdk/current/conf/logging.properties", + "//third_party/jdk/current/conf/security/java.security", + "//third_party/jdk/current/lib/ct.sym", + "//third_party/jdk/current/lib/jrt-fs.jar", + "//third_party/jdk/current/lib/jvm.cfg", + "//third_party/jdk/current/lib/libawt.so", + "//third_party/jdk/current/lib/libawt_headless.so", + "//third_party/jdk/current/lib/libawt_xawt.so", + "//third_party/jdk/current/lib/libjava.so", + "//third_party/jdk/current/lib/libjimage.so", + "//third_party/jdk/current/lib/libjli.so", + "//third_party/jdk/current/lib/libjsvml.so", + "//third_party/jdk/current/lib/libmanagement.so", + "//third_party/jdk/current/lib/libmanagement_ext.so", + "//third_party/jdk/current/lib/libnet.so", + "//third_party/jdk/current/lib/libnio.so", + "//third_party/jdk/current/lib/libverify.so", + "//third_party/jdk/current/lib/libzip.so", + "//third_party/jdk/current/lib/modules", + "//third_party/jdk/current/lib/server/classes.jsa", + "//third_party/jdk/current/lib/server/libjvm.so", + "//third_party/jdk/current/lib/tzdb.dat", + ] + + # Actions that use java should add this as inputs so that they are rebuilt # when the JDK changes. - java_path_for_inputs = "//third_party/jdk/current/bin/java.chromium" + java_paths_for_inputs = [ + "//third_party/jdk/current/bin/java", + "//third_party/jdk/current/bin/java.chromium", + ] + _common_inputs_for_jre_jdk + + javac_paths_for_inputs = + [ "//third_party/jdk/current/bin/javac" ] + _common_inputs_for_jre_jdk # TODO(crbug.com/1426605): Remove. use_upstream_errorprone_annotations_threadsafe = true diff --git a/naiveproxy/src/build/config/android/internal_rules.gni b/naiveproxy/src/build/config/android/internal_rules.gni index 2034349b47..b1bf874b29 100644 --- a/naiveproxy/src/build/config/android/internal_rules.gni +++ b/naiveproxy/src/build/config/android/internal_rules.gni @@ -121,42 +121,39 @@ build_config_target_suffix = "__build_config_crbug_908819" # See build/android/gyp/write_build_config.py and # build/android/gyp/util/build_utils.py:ExpandFileArgs template("write_build_config") { - _type = invoker.type - _parent_invoker = invoker.invoker - _target_label = - get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain") - - # Ensure targets match naming patterns so that __assetres, __header, __host, - # and __validate targets work properly. - if (filter_exclude([ _type ], _java_resource_types) == []) { - if (filter_exclude([ _target_label ], java_resource_patterns) != []) { - assert(false, "Invalid java resource target name: $_target_label") - } - } else if (filter_exclude([ _type ], _java_library_types) == []) { - if (filter_exclude([ _target_label ], java_library_patterns) != [] || - filter_exclude([ _target_label ], java_resource_patterns) == []) { - assert(false, "Invalid java library target name: $_target_label") - } - } else if (_type == "group") { - if (filter_exclude([ _target_label ], java_target_patterns) != []) { - assert(false, "Invalid java target name: $_target_label") - } - } else if (filter_exclude([ _type ], _java_leaf_types) != []) { - assert(false, "This java type needs a category: $_type") - } - - if (defined(invoker.public_target_label)) { - _target_label = invoker.public_target_label - } - action_with_pydeps(target_name) { - forward_variables_from(invoker, - [ - "deps", - "testonly", - ]) - if (!defined(deps)) { - deps = [] + forward_variables_from(invoker, [ "testonly" ]) + _type = invoker.type + _parent_invoker = invoker.invoker + _target_label = + get_label_info(":${_parent_invoker.target_name}", "label_no_toolchain") + + # Ensure targets match naming patterns so that __assetres, __header, __host, + # and __validate targets work properly. + if (filter_exclude([ _type ], _java_resource_types) == []) { + if (filter_exclude([ _target_label ], java_resource_patterns) != []) { + assert(false, "Invalid java resource target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_library_types) == []) { + if (filter_exclude([ _target_label ], java_library_patterns) != [] || + filter_exclude([ _target_label ], java_resource_patterns) == []) { + assert(false, "Invalid java library target name: $_target_label") + } + } else if (_type == "group") { + if (filter_exclude([ _target_label ], java_target_patterns) != []) { + assert(false, "Invalid java target name: $_target_label") + } + } else if (filter_exclude([ _type ], _java_leaf_types) != []) { + assert(false, "This java type needs a category: $_type") + } + + if (defined(invoker.public_target_label)) { + _target_label = invoker.public_target_label + } + + deps = [] + if (defined(invoker.deps)) { + deps = invoker.deps } if (defined(invoker.android_manifest_dep)) { deps += [ invoker.android_manifest_dep ] @@ -1090,12 +1087,11 @@ if (enable_java_templates) { script = "//build/android/gyp/lint.py" depfile = "$target_gen_dir/$target_name.d" - inputs = [ - java_path_for_inputs, - _lint_jar_path, - _custom_lint_jar_path, - _backported_methods, - ] + inputs = java_paths_for_inputs + [ + _lint_jar_path, + _custom_lint_jar_path, + _backported_methods, + ] args = [ "--target-name", @@ -1218,12 +1214,11 @@ if (enable_java_templates) { _script = "//build/android/gyp/proguard.py" _deps = invoker.deps - _inputs = [ - java_path_for_inputs, - invoker.build_config, - _r8_path, - _custom_r8_path, - ] + _inputs = java_paths_for_inputs + [ + invoker.build_config, + _r8_path, + _custom_r8_path, + ] if (defined(invoker.inputs)) { _inputs += invoker.inputs } @@ -1640,14 +1635,13 @@ if (enable_java_templates) { depfile = "$target_gen_dir/$target_name.d" outputs = [ invoker.output ] inputs = [ - "$android_sdk/optional/android.test.base.jar", - "$android_sdk/optional/org.apache.http.legacy.jar", - "//third_party/jdk/current/bin/java", - _custom_d8_path, - _d8_path, - android_sdk_jar, - java_path_for_inputs, - ] + "$android_sdk/optional/android.test.base.jar", + "$android_sdk/optional/org.apache.http.legacy.jar", + "//third_party/jdk/current/bin/java", + _custom_d8_path, + _d8_path, + android_sdk_jar, + ] + java_paths_for_inputs if (defined(invoker.inputs)) { inputs += invoker.inputs } @@ -1780,8 +1774,7 @@ if (enable_java_templates) { _jacococli_jar = "//third_party/jacoco/lib/jacococli.jar" script = "//build/android/gyp/jacoco_instr.py" - inputs = invoker.source_files + [ - java_path_for_inputs, + inputs = invoker.source_files + java_paths_for_inputs + [ _jacococli_jar, invoker.input_jar_path, ] @@ -1899,11 +1892,10 @@ if (enable_java_templates) { "deps", ]) script = "//build/android/gyp/bytecode_processor.py" - inputs = [ - java_path_for_inputs, - invoker.build_config, - invoker.input_jar, - ] + inputs = java_paths_for_inputs + [ + invoker.build_config, + invoker.input_jar, + ] outputs = [ "$target_out_dir/$target_name.bytecode.stamp" ] _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) args = [ @@ -1944,12 +1936,11 @@ if (enable_java_templates) { script = "//build/android/gyp/merge_manifest.py" depfile = "$target_gen_dir/$target_name.d" - inputs = [ - java_path_for_inputs, - invoker.build_config, - invoker.input_manifest, - _manifest_merger_jar_path, - ] + inputs = java_paths_for_inputs + [ + invoker.build_config, + invoker.input_manifest, + _manifest_merger_jar_path, + ] outputs = [ invoker.output_manifest ] _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) @@ -2146,6 +2137,8 @@ if (enable_java_templates) { # Use resource IDs provided by another APK target when compiling resources # (via. "aapt2 link --stable-ids") # + # override_target_sdk: (optional) + # Update the manifest to target this SDK # # Output variables: # arsc_output: Path to output .ap_ file (optional). @@ -2173,10 +2166,43 @@ if (enable_java_templates) { _script = "//build/android/gyp/compile_resources.py" + _target_sdk_version = invoker.target_sdk_version + if(defined(invoker.override_target_sdk)) { + _target_sdk_version = invoker.override_target_sdk + } + _inputs = [ invoker.build_config, android_sdk_tools_bundle_aapt2, android_sdk_jar, + + # TODO(b/315080809#comment4): remove these files after fixing + # build/print_python_deps.py. + "//third_party/protobuf/python/google/__init__.py", + "//third_party/protobuf/python/google/protobuf/__init__.py", + "//third_party/protobuf/python/google/protobuf/descriptor.py", + "//third_party/protobuf/python/google/protobuf/descriptor_database.py", + "//third_party/protobuf/python/google/protobuf/descriptor_pb2.py", + "//third_party/protobuf/python/google/protobuf/descriptor_pool.py", + "//third_party/protobuf/python/google/protobuf/internal/__init__.py", + "//third_party/protobuf/python/google/protobuf/internal/api_implementation.py", + "//third_party/protobuf/python/google/protobuf/internal/builder.py", + "//third_party/protobuf/python/google/protobuf/internal/containers.py", + "//third_party/protobuf/python/google/protobuf/internal/decoder.py", + "//third_party/protobuf/python/google/protobuf/internal/encoder.py", + "//third_party/protobuf/python/google/protobuf/internal/enum_type_wrapper.py", + "//third_party/protobuf/python/google/protobuf/internal/extension_dict.py", + "//third_party/protobuf/python/google/protobuf/internal/message_listener.py", + "//third_party/protobuf/python/google/protobuf/internal/python_message.py", + "//third_party/protobuf/python/google/protobuf/internal/type_checkers.py", + "//third_party/protobuf/python/google/protobuf/internal/well_known_types.py", + "//third_party/protobuf/python/google/protobuf/internal/wire_format.py", + "//third_party/protobuf/python/google/protobuf/message.py", + "//third_party/protobuf/python/google/protobuf/message_factory.py", + "//third_party/protobuf/python/google/protobuf/reflection.py", + "//third_party/protobuf/python/google/protobuf/symbol_database.py", + "//third_party/protobuf/python/google/protobuf/text_encoding.py", + "//third_party/protobuf/python/google/protobuf/text_format.py", ] _rebased_build_config = rebase_path(invoker.build_config, root_build_dir) @@ -2189,7 +2215,7 @@ if (enable_java_templates) { "--dependencies-res-zips=@FileArg($_rebased_build_config:deps_info:dependency_zips)", "--extra-res-packages=@FileArg($_rebased_build_config:deps_info:extra_package_names)", "--min-sdk-version=${invoker.min_sdk_version}", - "--target-sdk-version=${invoker.target_sdk_version}", + "--target-sdk-version=${_target_sdk_version}", "--webp-cache-dir=obj/android-webp-cache", ] @@ -2539,10 +2565,7 @@ if (enable_java_templates) { script = "//build/android/gyp/unused_resources.py" depfile = "$target_gen_dir/${target_name}.d" _unused_resources_script = "$root_build_dir/bin/helper/unused_resources" - inputs = [ - _unused_resources_script, - java_path_for_inputs, - ] + inputs = [ _unused_resources_script ] + java_paths_for_inputs outputs = [ invoker.output_config, invoker.output_r_txt, @@ -3008,7 +3031,7 @@ if (enable_java_templates) { ] } else { script = "//build/android/gyp/compile_java.py" - inputs = [ "//third_party/jdk/current/bin/javac" ] + inputs = javac_paths_for_inputs } if (target_name == "chrome_java__header") { @@ -3030,8 +3053,7 @@ if (enable_java_templates) { "$android_sdk/optional/android.test.base.jar", "$android_sdk/optional/org.apache.http.legacy.jar", _build_config, - java_path_for_inputs, - ] + ] + java_paths_for_inputs if (invoker.source_files != []) { inputs += [ invoker.target_sources_file ] @@ -3134,6 +3156,11 @@ if (enable_java_templates) { "--processorpath=@FileArg($_rebased_errorprone_buildconfig:deps_info:host_classpath)", "--enable-errorprone", ] + inputs += [ + # errorprone requires the plugin directory to detect src dir. + # https://source.chromium.org/chromium/chromium/src/+/main:tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/UseNetworkAnnotations.java;l=84;drc=dfd88085261b662a5c0a1abea1a3b120b08e8e48 + "//tools/android/errorprone_plugin/OWNERS", + ] } if (defined(invoker.skip_build_server) && invoker.skip_build_server) { # Nocompile tests need lint to fail through ninja. @@ -3973,12 +4000,11 @@ if (enable_java_templates) { _rebased_build_config = rebase_path(_build_config, root_build_dir) action_with_pydeps(_rewritten_jar_target_name) { script = "//build/android/gyp/bytecode_rewriter.py" - inputs = [ - java_path_for_inputs, - _rewriter_path, - _build_config, - _unprocessed_jar_path, - ] + inputs = java_paths_for_inputs + [ + _rewriter_path, + _build_config, + _unprocessed_jar_path, + ] outputs = [ _rewritten_jar ] depfile = "$target_gen_dir/$target_name.d" args = [ @@ -4254,10 +4280,14 @@ if (enable_java_templates) { [ get_path_info(source_file, "abspath") ] } } - + _abs_jar_path = "" + if (defined(invoker.jar_path)) { + _abs_jar_path = get_path_info(invoker.jar_path, "abspath") + } # See crbug/1449896 for more details about the metadata fields # and why they are added. metadata = { + jar_path = [ _abs_jar_path ] source_files = _abs_path_source_files all_deps = _abs_deps target_type = [ _type ] diff --git a/naiveproxy/src/build/config/android/rules.gni b/naiveproxy/src/build/config/android/rules.gni index bc9ec9848e..693c79cca1 100644 --- a/naiveproxy/src/build/config/android/rules.gni +++ b/naiveproxy/src/build/config/android/rules.gni @@ -468,12 +468,6 @@ if (enable_java_templates && is_android) { rebase_path(depfile, root_build_dir), ] } - if (defined(invoker.main_component_library)) { - args += [ - "--main-component-library", - invoker.main_component_library, - ] - } if (defined(invoker.enable_chromium_linker) && invoker.enable_chromium_linker) { args += [ "--enable-chromium-linker" ] @@ -1187,6 +1181,7 @@ if (enable_java_templates && is_android) { arsc_output = _resource_arsc_output min_sdk_version = default_min_sdk_version target_sdk_version = android_sdk_version + forward_variables_from(invoker, [ "override_target_sdk" ]) } # apkbuilder step needed only to add android assets to the .ap_ file. @@ -2010,9 +2005,8 @@ if (enable_java_templates && is_android) { # loadable_modules: List of paths to native libraries to include. Different # from |shared_libraries| in that: # * dependencies of this .so are not automatically included - # * ".cr.so" is never added # * they are not side-loaded when incremental_install=true. - # * use_chromium_linker, and enable_relocation_packing do not apply + # * they are not included in NativeLibraries.java # Use this instead of shared_libraries when you are going to load the library # conditionally, and only when shared_libraries doesn't work for you. # secondary_abi_loadable_modules: This is the loadable_modules analog to @@ -2093,9 +2087,6 @@ if (enable_java_templates && is_android) { # compiling sources given to this target (optional). # bundles_supported: Enable Java code to treat this target as a bundle # whether (by default determined by the target type). - # main_component_library: Specifies the name of the base component's library - # in a component build. If given, the system will find dependent native - # libraries at runtime by inspecting this library (optional). # expected_libs_and_assets: Verify the list of included native libraries # and assets is consistent with the given expectation file. # expected_libs_and_assets_base: Treat expected_libs_and_assets as a diff @@ -2367,6 +2358,7 @@ if (enable_java_templates && is_android) { "expected_android_manifest_version_code_offset", "manifest_package", "max_sdk_version", + "override_target_sdk", "package_id", "png_to_webp", "r_java_root_package_name", @@ -2554,8 +2546,6 @@ if (enable_java_templates && is_android) { } if (_generate_native_libraries_java) { write_native_libraries_java("${_template_name}__native_libraries") { - forward_variables_from(invoker, [ "main_component_library" ]) - # Do not add a dep on the generated_file target in order to avoid having # to build the native libraries before this target. The dependency is # instead captured via a depfile. @@ -3266,7 +3256,6 @@ if (enable_java_templates && is_android) { "max_sdk_version", "mergeable_android_manifests", "product_config_java_packages", - "main_component_library", "min_sdk_version", "native_lib_placeholders", "never_incremental", @@ -3401,11 +3390,11 @@ if (enable_java_templates && is_android) { "javac_args", "loadable_modules", "product_config_java_packages", - "main_component_library", "manifest_package", "max_sdk_version", "min_sdk_version", "mergeable_android_manifests", + "override_target_sdk", "module_name", "native_lib_placeholders", "package_id", @@ -3629,7 +3618,7 @@ if (enable_java_templates && is_android) { data += invoker.data } - deps = [ "//testing/android/broker:broker_java" ] + deps = [] if (defined(invoker.deps)) { deps += invoker.deps } @@ -4355,6 +4344,8 @@ if (enable_java_templates && is_android) { if (!defined(requires_android)) { requires_android = true } + include_java_resources = !defined(invoker.include_java_resources) || + invoker.include_java_resources supports_android = true jar_path = "$_output_path/classes.jar" aar_path = invoker.aar_path @@ -4690,11 +4681,10 @@ if (enable_java_templates && is_android) { _stamp = "${target_out_dir}/${target_name}.trace_event_rewrite.stamp" action_with_pydeps(_rewritten_jar_target_name) { script = "//build/android/gyp/trace_event_bytecode_rewriter.py" - inputs = [ - java_path_for_inputs, - _rewriter_path, - _build_config, - ] + inputs = java_paths_for_inputs + [ + _rewriter_path, + _build_config, + ] outputs = [ _stamp ] depfile = "$target_gen_dir/$_rewritten_jar_target_name.d" args = [ @@ -4950,10 +4940,8 @@ if (enable_java_templates && is_android) { _bundle_target_name = "${_target_name}__bundle" action_with_pydeps(_bundle_target_name) { script = "//build/android/gyp/create_app_bundle.py" - inputs = _all_module_zip_paths + _all_module_build_configs + [ - _BUNDLETOOL_JAR_PATH, - java_path_for_inputs, - ] + inputs = _all_module_zip_paths + _all_module_build_configs + + [ _BUNDLETOOL_JAR_PATH ] + java_paths_for_inputs outputs = [ _bundle_path ] deps = _all_create_module_targets + [ ":$_build_config_target" ] args = [ @@ -5185,11 +5173,10 @@ if (enable_java_templates && is_android) { _apks_path = "$root_build_dir/apks/$_bundle_name.apks" action_with_pydeps("${_target_name}_apks") { script = "//build/android/gyp/create_app_bundle_apks.py" - inputs = [ - java_path_for_inputs, - _bundle_path, - _BUNDLETOOL_JAR_PATH, - ] + inputs = java_paths_for_inputs + [ + _bundle_path, + _BUNDLETOOL_JAR_PATH, + ] outputs = [ _apks_path ] data = [ _apks_path ] args = [ @@ -5248,10 +5235,7 @@ if (enable_java_templates && is_android) { _name = get_path_info(invoker.bundle_path, "name") _output_path = "$_dir/$_name.minimal.apks" outputs = [ _output_path ] - inputs = [ - invoker.bundle_path, - java_path_for_inputs, - ] + inputs = [ invoker.bundle_path ] + java_paths_for_inputs args = [ "--bundle", rebase_path(invoker.bundle_path, root_build_dir), diff --git a/naiveproxy/src/build/config/android/system_image.gni b/naiveproxy/src/build/config/android/system_image.gni index 3ada84259e..d48b562f1c 100644 --- a/naiveproxy/src/build/config/android/system_image.gni +++ b/naiveproxy/src/build/config/android/system_image.gni @@ -54,6 +54,11 @@ template("system_image_stub_apk") { } } + _target_sdk_version = default_android_sdk_version + if (defined(invoker.override_target_sdk)) { + _target_sdk_version = invoker.override_target_sdk + } + action_with_pydeps(_resource_apk_target_name) { script = "//build/android/gyp/compile_resources.py" inputs = [ @@ -65,7 +70,7 @@ template("system_image_stub_apk") { "--aapt2-path", rebase_path(android_sdk_tools_bundle_aapt2, root_build_dir), "--min-sdk-version=$default_min_sdk_version", - "--target-sdk-version=$default_android_sdk_version", + "--target-sdk-version=$_target_sdk_version", "--android-manifest", rebase_path(_manifest_path, root_build_dir), "--arsc-path", @@ -150,6 +155,7 @@ template("system_image_apks") { [ "static_library_name", "static_library_version", + "override_target_sdk" ]) package_info_from_target = invoker.apk_or_bundle_target stub_output = invoker.stub_output diff --git a/naiveproxy/src/build/config/chromeos/rules.gni b/naiveproxy/src/build/config/chromeos/rules.gni index cbd552711a..0b71d77fc4 100644 --- a/naiveproxy/src/build/config/chromeos/rules.gni +++ b/naiveproxy/src/build/config/chromeos/rules.gni @@ -68,11 +68,8 @@ if (cros_sdk_version != "") { ] if (_cros_is_vm) { # VM-related tools. - _symlinks += [ - rebase_path("${_cache_path_prefix}+sys-firmware/seabios"), - rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz"), - rebase_path("${_cache_path_prefix}+app-emulation/qemu"), - ] + _symlinks += + [ rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz") ] } _symlink_map += [ [ b, @@ -150,11 +147,7 @@ template("generate_chromeos_sdk_deps") { } if (_cros_is_vm) { # Add vm sdk items. - _sdk_data += [ - _symlink_targets[3], - _symlink_targets[4], - _symlink_targets[5], - ] + _sdk_data += [ _symlink_targets[3] ] } } } diff --git a/naiveproxy/src/build/config/clang/BUILD.gn b/naiveproxy/src/build/config/clang/BUILD.gn index d3054d14d9..5f171714f0 100644 --- a/naiveproxy/src/build/config/clang/BUILD.gn +++ b/naiveproxy/src/build/config/clang/BUILD.gn @@ -31,16 +31,42 @@ config("find_bad_constructs") { "-Xclang", "check-stack-allocated", + # TODO(danakj): Delete this after the next clang roll. + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "check-allow-auto-typedefs-better-nested", + "-Xclang", "-plugin-arg-find-bad-constructs", "-Xclang", "check-raw-ptr-to-stack-allocated", - # TODO(https://crbug.com/1504043): Remove when raw_ptr check has been enabled for the dawn repo. + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "disable-check-raw-ptr-to-stack-allocated-error", + + # TODO(https://crbug.com/1504043): Remove when raw_ptr check has been + # enabled for the dawn repo. "-Xclang", "-plugin-arg-find-bad-constructs", "-Xclang", "raw-ptr-exclude-path=/third_party/dawn/", + + # TODO(bartekn): Remove once clang plugin with crrev.com/c/5205312 rolls. + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "raw-ptr-exclude-path=base/logging.h", + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "raw-ptr-exclude-path=base/synchronization/lock_impl.h", + "-Xclang", + "-plugin-arg-find-bad-constructs", + "-Xclang", + "raw-ptr-exclude-path=base/check.h", ] if (is_linux || is_chromeos || is_android || is_fuchsia) { diff --git a/naiveproxy/src/build/config/compiler/BUILD.gn b/naiveproxy/src/build/config/compiler/BUILD.gn index b7f113bc5e..180d8d8223 100644 --- a/naiveproxy/src/build/config/compiler/BUILD.gn +++ b/naiveproxy/src/build/config/compiler/BUILD.gn @@ -383,12 +383,7 @@ config("compiler") { cflags += [ "-fstack-protector" ] } } else if ((is_posix && !is_chromeos && !is_nacl) || is_fuchsia) { - # TODO(phajdan.jr): Use -fstack-protector-strong when our gcc supports it. - # See also https://crbug.com/533294 - # The x86 toolchain currently has problems with stack-protector. - if (is_android && current_cpu == "x86") { - cflags += [ "-fno-stack-protector" ] - } else if (current_os != "aix") { + if (current_os != "aix") { # Not available on aix. cflags += [ "-fstack-protector" ] } @@ -1039,9 +1034,14 @@ config("compiler") { if (rust_abi_target != "") { rustflags += [ "--target=$rust_abi_target" ] } - if (!use_thin_lto) { + if (!use_thin_lto || !toolchain_supports_rust_thin_lto) { # Don't include bitcode if it won't be used. rustflags += [ "-Cembed-bitcode=no" ] + + # Disable "automatic" ThinLTO between codegen units. The weak symbol + # resolution across units can have surprising effects on linking, see + # crbug.com/324126269 and github.com/rust-lang/rust/issues/120842. + rustflags += [ "-Clto=no" ] } if (is_official_build) { rustflags += [ "-Ccodegen-units=1" ] @@ -1883,6 +1883,9 @@ config("default_warnings") { cflags_cc += [ # TODO(https://crbug.com/1474434): fix and reenable "-Wno-missing-field-initializers", + + # TODO(https://crbug.com/324953188): fix and reenable + "-Wno-extra-qualification", ] } @@ -1927,6 +1930,7 @@ config("default_warnings") { cflags += [ "-Wno-error=unknown-warning-option", "-Wno-error=unused-command-line-argument", + "-Wno-error=unknown-pragmas", ] } } @@ -1980,6 +1984,35 @@ config("prevent_unsafe_narrowing") { } } +# unsafe_buffer_warning ------------------------------------------------------- + +# Paths of third-party headers that violate Wunsafe-buffer-usage, but which we +# have been unable to fix yet. We use this list to be able to make progress and +# enable the warning on code that we do control/own. +# +# WARNING: This will disable all warnings in the files. ONLY USE THIS for +# third-party code which we do not control/own. Fix the warnings instead in +# our own code. +if (is_clang) { + unsafe_buffer_warning_header_allowlist = + [ "third_party/googletest/src/googletest/include/gtest" ] +} + +# Enables warnings on pointer arithmetic/indexing or calls to functions +# annotated with `UNSAFE_BUFFER_USAGE`. +config("unsafe_buffer_warning") { + if (is_clang) { + cflags = [ "-Wunsafe-buffer-usage" ] + foreach(h, unsafe_buffer_warning_header_allowlist) { + if (is_win) { + cflags += [ "/clang:--system-header-prefix=$h" ] + } else { + cflags += [ "--system-header-prefix=$h" ] + } + } + } +} + # chromium_code --------------------------------------------------------------- # # Toggles between higher and lower warnings for code that is (or isn't) @@ -2420,32 +2453,22 @@ config("optimize") { # to optimize for performance like `/O2` for clang. rustflags = [] } - } else if (optimize_for_size) { + } else if (optimize_for_size || is_chromeos) { # Favor size over speed. - if (is_clang) { - cflags = [ "-Oz" ] + common_optimize_on_cflags + # -Os in clang is more of a size-conscious -O2 than "size at any cost" (AKA -Oz). - if (use_ml_inliner && is_a_target_toolchain) { - cflags += [ - "-mllvm", - "-enable-ml-inliner=release", - ] - } - } else { + if (is_fuchsia) { + cflags = [ "-Oz" ] + common_optimize_on_cflags + } else { cflags = [ "-Os" ] + common_optimize_on_cflags } - # Like with `-Oz` on Clang, `-Copt-level=z` will also turn off loop - # vectorization. - rustflags = [ "-Copt-level=z" ] - } else if (is_chromeos) { - # TODO(gbiv): This is partially favoring size over speed. CrOS exclusively - # uses clang, and -Os in clang is more of a size-conscious -O2 than "size at - # any cost" (AKA -Oz). It'd be nice to: - # - Make `optimize_for_size` apply to all platforms where we're optimizing - # for size by default (so, also Windows) - # - Investigate -Oz here, maybe just for ARM? - cflags = [ "-Os" ] + common_optimize_on_cflags + if (is_clang && use_ml_inliner && is_a_target_toolchain && !is_chromeos) { + cflags += [ + "-mllvm", + "-enable-ml-inliner=release", + ] + } # Similar to clang, we optimize with `-Copt-level=s` to keep loop # vectorization while otherwise optimizing for size. diff --git a/naiveproxy/src/build/config/compiler/pgo/BUILD.gn b/naiveproxy/src/build/config/compiler/pgo/BUILD.gn index f8293b2ef0..d047c7e4bb 100644 --- a/naiveproxy/src/build/config/compiler/pgo/BUILD.gn +++ b/naiveproxy/src/build/config/compiler/pgo/BUILD.gn @@ -58,7 +58,9 @@ config("pgo_optimization_flags") { _pgo_target = "linux" } else if (is_chromeos_lacros) { if (target_cpu == "arm") { - _pgo_target = "lacros-arm" + # We don't have the arm device to train arm pgo data. So Lacros arm + # would use arm64 profile. + _pgo_target = "lacros-arm64" } else if (target_cpu == "arm64") { _pgo_target = "lacros-arm64" } else { diff --git a/naiveproxy/src/build/config/compiler/pgo/pgo.gni b/naiveproxy/src/build/config/compiler/pgo/pgo.gni index a85334d816..008a57522a 100644 --- a/naiveproxy/src/build/config/compiler/pgo/pgo.gni +++ b/naiveproxy/src/build/config/compiler/pgo/pgo.gni @@ -5,6 +5,7 @@ import("//build/config/cast.gni") import("//build/config/chrome_build.gni") import("//build/config/chromeos/ui_mode.gni") +import("//build/config/cronet/config.gni") import("//build/config/dcheck_always_on.gni") import("//build/config/features.gni") import("//build/config/ios/config.gni") @@ -20,7 +21,7 @@ declare_args() { # to think some code is hotter than it actually is, potentially causing very # bad compile times. chrome_pgo_phase = 0 - if (!dcheck_always_on && is_official_build && + if (!is_cronet_build && !dcheck_always_on && is_official_build && # TODO(crbug.com/1336055): Update this now-outdated condition with regard # to chromecast and determine whether chromeos_is_browser_only is # obsolete. diff --git a/naiveproxy/src/build/config/fuchsia/gn_configs.gni b/naiveproxy/src/build/config/fuchsia/gn_configs.gni index ca9e2c67a1..23864dea58 100644 --- a/naiveproxy/src/build/config/fuchsia/gn_configs.gni +++ b/naiveproxy/src/build/config/fuchsia/gn_configs.gni @@ -9,7 +9,7 @@ declare_args() { # value to specify the API level the packages produced from this repository # should be targeting, e.g. in their top-level //.gn file. A value of -1 # means that no API level will be passed to the tools that consumes it. - fuchsia_target_api_level = 12 + fuchsia_target_api_level = 16 # Path to the fuchsia SDK. This is intended for use in other templates & # rules to reference the contents of the fuchsia SDK. diff --git a/naiveproxy/src/build/config/fuchsia/test/README.md b/naiveproxy/src/build/config/fuchsia/test/README.md index 5f4b4b4269..4825fff16e 100644 --- a/naiveproxy/src/build/config/fuchsia/test/README.md +++ b/naiveproxy/src/build/config/fuchsia/test/README.md @@ -48,10 +48,6 @@ Capabilities required by anything that uses `//base/test` when running in the (default) `chromium` test realm. It is the default base fragment for most `test()` Components. -The system-wide `config-data` directory capability is routed to tests running in -the realm so that individual tests may route subdirectories as needed. -TODO(crbug.com/1360077): Remove this after migrating to the new mechanism. - #### logger.shard.test-cml For tests that test logging functionality by providing `fuchsia.logger.Log`. diff --git a/naiveproxy/src/build/config/fuchsia/test/minimum.shard.test-cml b/naiveproxy/src/build/config/fuchsia/test/minimum.shard.test-cml index 78e4d46711..6f0fed9f53 100644 --- a/naiveproxy/src/build/config/fuchsia/test/minimum.shard.test-cml +++ b/naiveproxy/src/build/config/fuchsia/test/minimum.shard.test-cml @@ -24,11 +24,6 @@ } ], use: [ - { - directory: "config-data", - rights: [ "r*" ], - path: "/config/data", - }, // Holds ICU time zone data files. // See: // https://fuchsia.dev/fuchsia-src/concepts/process/namespaces?typical_directory_structure diff --git a/naiveproxy/src/build/config/fuchsia/test/system_test_minimum.shard.test-cml b/naiveproxy/src/build/config/fuchsia/test/system_test_minimum.shard.test-cml index 6d9e515aa1..46aeadad28 100644 --- a/naiveproxy/src/build/config/fuchsia/test/system_test_minimum.shard.test-cml +++ b/naiveproxy/src/build/config/fuchsia/test/system_test_minimum.shard.test-cml @@ -6,11 +6,6 @@ "syslog/client.shard.cml", ], use: [ - { - directory: "config-data", - rights: [ "r*" ], - path: "/config/data", - }, { directory: "tzdata-icu", rights: [ "r*" ], diff --git a/naiveproxy/src/build/config/ios/BUILD.gn b/naiveproxy/src/build/config/ios/BUILD.gn index 4360f328cb..bddf5bd8a2 100644 --- a/naiveproxy/src/build/config/ios/BUILD.gn +++ b/naiveproxy/src/build/config/ios/BUILD.gn @@ -88,6 +88,7 @@ config("compiler") { if (ios_is_app_extension) { ldflags += [ "-fapplication-extension" ] + cflags += [ "-fapplication-extension" ] } } diff --git a/naiveproxy/src/build/config/ios/rules.gni b/naiveproxy/src/build/config/ios/rules.gni index be2737de05..5d0dbc7ce9 100644 --- a/naiveproxy/src/build/config/ios/rules.gni +++ b/naiveproxy/src/build/config/ios/rules.gni @@ -502,6 +502,10 @@ template("ios_info_plist") { # if omitted. Will be used to set BUNDLE_IDENTIFIER when generating # the application Info.plist # +# orderfile_path: +# (optional) string, path to an orderfile passed to the linker in order +# to improve application launch performance. +# # For more information, see "gn help executable". template("ios_app_bundle") { _output_name = target_name @@ -607,6 +611,22 @@ template("ios_app_bundle") { visibility += [ ":${_variant.target_name}" ] } + if (defined(invoker.orderfile_path)) { + orderfile_path = invoker.orderfile_path + if (!defined(ldflags)) { + ldflags = [] + } + ldflags += [ + "-Wl,-order_file", + "-Wl," + rebase_path(orderfile_path, root_build_dir), + ] + + if (!defined(inputs)) { + inputs = [] + } + inputs += [ orderfile_path ] + } + if (target_environment == "simulator") { if (!defined(deps)) { deps = [] diff --git a/naiveproxy/src/build/config/linux/pkg_config.gni b/naiveproxy/src/build/config/linux/pkg_config.gni index 0d873903c5..591afd7d1d 100644 --- a/naiveproxy/src/build/config/linux/pkg_config.gni +++ b/naiveproxy/src/build/config/linux/pkg_config.gni @@ -105,13 +105,13 @@ template("pkg_config") { cflags = pkgresult[1] foreach(include, pkgresult[0]) { + # We want the system include paths to use -isystem instead of -I to + # suppress warnings in those headers. if (use_sysroot) { - # We want the system include paths to use -isystem instead of -I to - # suppress warnings in those headers. include_relativized = rebase_path(include, root_build_dir) cflags += [ "-isystem$include_relativized" ] } else { - cflags += [ "-I$include" ] + cflags += [ "-isystem$include" ] } } diff --git a/naiveproxy/src/build/config/openwrt/BUILD.gn b/naiveproxy/src/build/config/openwrt/BUILD.gn index 4aa3c5fb42..124817262c 100644 --- a/naiveproxy/src/build/config/openwrt/BUILD.gn +++ b/naiveproxy/src/build/config/openwrt/BUILD.gn @@ -47,7 +47,7 @@ config("compiler") { abi = "musl" if (current_cpu == "arm") { - abi = "muslgnueabi" + abi = "musleabi" arch = "arm" } else if (current_cpu == "arm64") { arch = "aarch64" diff --git a/naiveproxy/src/build/config/rust.gni b/naiveproxy/src/build/config/rust.gni index e98d9139f6..9b0ee754ba 100644 --- a/naiveproxy/src/build/config/rust.gni +++ b/naiveproxy/src/build/config/rust.gni @@ -66,6 +66,17 @@ declare_args() { # you can specify whether it supports nacl here. rust_toolchain_supports_nacl = false + # Whether artifacts produced by the Rust compiler can participate in ThinLTO. + # + # One important consideration is whether the linker uses the same LLVM + # version as `rustc` (i.e. if it can understand the LLVM-IR from the + # compilation artifacts produced by `rustc`). In LaCrOS and ash builds this + # may not be true - see b/299483903. + # + # TODO(https://crbug.com/1482525): Re-enable ThinLTO for Rust on LaCrOS + # TODO(b/300937673): Re-enable ThinLTO for Rust on ash-chrome + toolchain_supports_rust_thin_lto = !is_chromeos + # Any extra std rlibs in your Rust toolchain, relative to the standard # Rust toolchain. Typically used with 'rust_sysroot_absolute' added_rust_stdlib_libs = [] @@ -156,17 +167,6 @@ if (enable_rust) { # for gtests from the `//testing/test:test` template. can_build_rust_unit_tests = toolchain_has_rust && !is_android -# Whether artifacts produced by the Rust compiler can participate in ThinLTO. -# -# One important consideration is whether the linker uses the same LLVM -# version as `rustc` (i.e. if it can understand the LLVM-IR from the -# compilation artifacts produced by `rustc`). In LaCrOS and ash builds this may -# not be true - see b/299483903. -# -# TODO(https://crbug.com/1482525): Re-enable ThinLTO for Rust on LaCrOS -# TODO(b/300937673): Re-enable ThinLTO for Rust on ash-chrome -toolchain_supports_rust_thin_lto = !is_chromeos - # We want to store rust_sysroot as a source-relative variable for ninja # portability. In practice if an external toolchain was specified, it might # be an absolute path, but we'll do our best. diff --git a/naiveproxy/src/build/config/sanitizers/BUILD.gn b/naiveproxy/src/build/config/sanitizers/BUILD.gn index 59c0cbbfea..8cda968604 100644 --- a/naiveproxy/src/build/config/sanitizers/BUILD.gn +++ b/naiveproxy/src/build/config/sanitizers/BUILD.gn @@ -433,6 +433,10 @@ config("coverage_flags") { ] } } + if (sanitizer_coverage_allowlist != "") { + cflags += [ "-fsanitize-coverage-allowlist=" + + rebase_path(sanitizer_coverage_allowlist, root_build_dir) ] + } } } diff --git a/naiveproxy/src/build/config/sanitizers/sanitizers.gni b/naiveproxy/src/build/config/sanitizers/sanitizers.gni index 0cf761ab2c..bf0dfdad65 100644 --- a/naiveproxy/src/build/config/sanitizers/sanitizers.gni +++ b/naiveproxy/src/build/config/sanitizers/sanitizers.gni @@ -96,6 +96,10 @@ declare_args() { # trace-pc-guard,indirect-calls sanitizer_coverage_flags = "" + # A sanitizer coverage allowlist, specifying exactly which + # files or symbol names should be instrumented, rather than all of them. + sanitizer_coverage_allowlist = "" + # When enabled, only relevant sanitizer defines are set, but compilation # happens with no extra flags. This is useful when in component build # enabling sanitizers only in some of the components. @@ -323,6 +327,10 @@ assert( "Chromium mac_clang_x64 toolchain on iOS distribution. Please set " + "the argument value to false.") +assert( + sanitizer_coverage_allowlist == "" || use_sanitizer_coverage, + "Can't specify a sanitizer coverage allowlist without using sanitizer coverage.") + # Use these lists of configs to disable instrumenting code that is part of a # fuzzer, but which isn't being targeted (such as libprotobuf-mutator, *.pb.cc # and libprotobuf when they are built as part of a proto fuzzer). Adding or diff --git a/naiveproxy/src/build/config/siso/PRESUBMIT.py b/naiveproxy/src/build/config/siso/PRESUBMIT.py index dac9feedfb..4099f0b5cf 100644 --- a/naiveproxy/src/build/config/siso/PRESUBMIT.py +++ b/naiveproxy/src/build/config/siso/PRESUBMIT.py @@ -15,13 +15,10 @@ def CheckTryjobFooters(input_api, output_api): message = ( "Missing 'Cq-Include-Trybots:' field required for Siso config changes" "\nPlease add the following fields to run Siso tryjobs.\n\n" - "Cq-Include-Trybots: luci.chromium.try:chromeos-amd64-generic-siso-rel\n" "Cq-Include-Trybots: luci.chromium.try:fuchsia-binary-size-siso\n" "Cq-Include-Trybots: luci.chromium.try:ios-simulator-siso\n" - "Cq-Include-Trybots: luci.chromium.try:linux-chromeos-compile-siso-dbg\n" "Cq-Include-Trybots: luci.chromium.try:linux_chromium_asan_siso_rel_ng\n" "Cq-Include-Trybots: luci.chromium.try:linux_chromium_compile_siso_dbg_ng\n" "Cq-Include-Trybots: luci.chromium.try:mac-siso-rel\n" - "Cq-Include-Trybots: luci.chromium.try:win_chromium_compile_siso_dbg_ng\n" ) return [output_api.PresubmitPromptWarning(message)] diff --git a/naiveproxy/src/build/config/siso/android.star b/naiveproxy/src/build/config/siso/android.star index c3e1ccf1b0..e4e337c100 100644 --- a/naiveproxy/src/build/config/siso/android.star +++ b/naiveproxy/src/build/config/siso/android.star @@ -20,8 +20,6 @@ def __filegroups(ctx): return {} def __step_config(ctx, step_config): - __input_deps(ctx, step_config["input_deps"]) - remote_run = True # Turn this to False when you do file access trace. step_config["rules"].extend([ # See also https://chromium.googlesource.com/chromium/src/build/+/HEAD/android/docs/java_toolchain.md @@ -53,9 +51,6 @@ def __step_config(ctx, step_config): "name": "android/compile_resources", "command_prefix": "python3 ../../build/android/gyp/compile_resources.py", "handler": "android_compile_resources", - "inputs": [ - "third_party/protobuf/python/google:pyprotolib", - ], "exclude_input_patterns": [ "*.h", "*.o", @@ -155,10 +150,6 @@ def __android_compile_resources_handler(ctx, cmd): # --webp-cache-dir=obj/android-webp-cache inputs = [] for i, arg in enumerate(cmd.args): - if arg in ["--aapt2-path", "--include-resources"]: - inputs.append(ctx.fs.canonpath(cmd.args[i + 1])) - if arg.startswith("--include-resources="): - inputs.append(ctx.fs.canonpath(arg.removeprefix("--include-resources="))) for k in ["--dependencies-res-zips=", "--dependencies-res-zip-overlays=", "--extra-res-packages="]: if arg.startswith(k): arg = arg.removeprefix(k) @@ -204,16 +195,12 @@ def __android_compile_java_handler(ctx, cmd): inputs = [] for i, arg in enumerate(cmd.args): - if arg == "--enable-errorprone": - # errorprone requires the plugin directory to detect src dir. - # https://source.chromium.org/chromium/chromium/src/+/main:tools/android/errorprone_plugin/src/org/chromium/tools/errorprone/plugin/UseNetworkAnnotations.java;l=84;drc=dfd88085261b662a5c0a1abea1a3b120b08e8e48 - inputs.append(ctx.fs.canonpath("../../tools/android/errorprone_plugin")) - # read .sources file. if arg.startswith("@"): sources = str(ctx.fs.read(ctx.fs.canonpath(arg.removeprefix("@")))).splitlines() - inputs += sources - for k in ["--java-srcjars=", "--classpath=", "--bootclasspath=", "--processorpath=", "--kotlin-jar-path="]: + for source in sources: + inputs.append(ctx.fs.canonpath(source)) + for k in ["--classpath=", "--bootclasspath=", "--processorpath="]: if arg.startswith(k): arg = arg.removeprefix(k) fn, v = __filearg(ctx, arg) @@ -241,7 +228,7 @@ def __android_dex_handler(ctx, cmd): for i, arg in enumerate(cmd.args): if arg == "--desugar-dependencies": outputs.append(ctx.fs.canonpath(cmd.args[i + 1])) - for k in ["--class-inputs=", "--bootclasspath=", "--classpath=", "--class-inputs-filearg=", "--dex-inputs=", "--dex-inputs-filearg="]: + for k in ["--class-inputs=", "--bootclasspath=", "--classpath=", "--class-inputs-filearg=", "--dex-inputs-filearg="]: if arg.startswith(k): arg = arg.removeprefix(k) fn, v = __filearg(ctx, arg) @@ -261,15 +248,7 @@ def __android_dex_handler(ctx, cmd): def __android_turbine_handler(ctx, cmd): inputs = [] - outputs = [] - out_fileslist = False - if cmd.args[len(cmd.args) - 1].startswith("@"): - out_fileslist = True for i, arg in enumerate(cmd.args): - if arg.startswith("--jar-path="): - jar_path = ctx.fs.canonpath(arg.removeprefix("--jar-path=")) - if out_fileslist: - outputs.append(jar_path + ".java_files_list.txt") for k in ["--classpath=", "--processorpath="]: if arg.startswith(k): arg = arg.removeprefix(k) @@ -282,7 +261,6 @@ def __android_turbine_handler(ctx, cmd): ctx.actions.fix( inputs = cmd.inputs + inputs, - outputs = cmd.outputs + outputs, ) def __deps_configs(ctx, f, seen, inputs): @@ -345,49 +323,10 @@ __handlers = { "android_write_build_config": __android_write_build_config_handler, } -def __input_deps(ctx, input_deps): - # TODO(crrev.com/c/4596899): Add Java inputs in GN config. - input_deps["third_party/jdk/current:current"] = [ - "third_party/jdk/current/bin/java", - "third_party/jdk/current/bin/java.chromium", - "third_party/jdk/current/conf/logging.properties", - "third_party/jdk/current/conf/security/java.security", - "third_party/jdk/current/lib/ct.sym", - "third_party/jdk/current/lib/jrt-fs.jar", - "third_party/jdk/current/lib/jvm.cfg", - "third_party/jdk/current/lib/libawt.so", - "third_party/jdk/current/lib/libawt_headless.so", - "third_party/jdk/current/lib/libawt_xawt.so", - "third_party/jdk/current/lib/libjava.so", - "third_party/jdk/current/lib/libjimage.so", - "third_party/jdk/current/lib/libjli.so", - "third_party/jdk/current/lib/libjsvml.so", - "third_party/jdk/current/lib/libmanagement.so", - "third_party/jdk/current/lib/libmanagement_ext.so", - "third_party/jdk/current/lib/libnet.so", - "third_party/jdk/current/lib/libnio.so", - "third_party/jdk/current/lib/libverify.so", - "third_party/jdk/current/lib/libzip.so", - "third_party/jdk/current/lib/modules", - "third_party/jdk/current/lib/server/classes.jsa", - "third_party/jdk/current/lib/server/libjvm.so", - "third_party/jdk/current/lib/tzdb.dat", - ] - input_deps["third_party/jdk/current/bin/java"] = [ - "third_party/jdk/current:current", - ] - input_deps["third_party/jdk/current/bin/javac"] = [ - "third_party/jdk/current:current", - ] - input_deps["third_party/protobuf/python/google/protobuf/__init__.py"] = [ - "third_party/protobuf/python/google:google", - ] - android = module( "android", enabled = __enabled, step_config = __step_config, filegroups = __filegroups, handlers = __handlers, - input_deps = __input_deps, ) diff --git a/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star b/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star index 70f18d44e7..9eb1c1cdb2 100644 --- a/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star +++ b/naiveproxy/src/build/config/siso/clang_code_coverage_wrapper.star @@ -204,7 +204,9 @@ def __run(ctx, args): files_to_instrument = [] if instrument_file: files_to_instrument = str(ctx.fs.read(ctx.fs.canonpath(instrument_file))).splitlines() - files_to_instrument = [ctx.fs.canonpath(f) for f in files_to_instrument] + + # strip() is for removing '\r' on Windows. + files_to_instrument = [ctx.fs.canonpath(f).strip() for f in files_to_instrument] should_remove_flags = False if compile_source_file not in force_list: @@ -215,6 +217,7 @@ def __run(ctx, args): if should_remove_flags: return _remove_flags_from_command(compile_command) + print("Keeping code coverage flags for %s" % compile_source_file) return compile_command clang_code_coverage_wrapper = module( diff --git a/naiveproxy/src/build/config/siso/clang_linux.star b/naiveproxy/src/build/config/siso/clang_linux.star index 15c88169f3..a47935256a 100644 --- a/naiveproxy/src/build/config/siso/clang_linux.star +++ b/naiveproxy/src/build/config/siso/clang_linux.star @@ -6,8 +6,23 @@ load("@builtin//path.star", "path") load("@builtin//struct.star", "module") +load("./android.star", "android") load("./clang_all.star", "clang_all") load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") +load("./config.star", "config") +load("./cros.star", "cros") + +# TODO: b/323091468 - Propagate target android ABI and android SDK version +# from GN, and remove remove hardcoded filegroups. +android_archs = [ + "aarch64-linux-android", + "arm-linux-androideabi", + "i686-linux-android", + "riscv64-linux-android", + "x86_64-linux-android", +] + +android_versions = list(range(21, 35)) def __filegroups(ctx): fg = { @@ -39,7 +54,36 @@ def __filegroups(ctx): "type": "glob", "includes": ["*"], }, + "third_party/llvm-build/Release+Asserts/lib/clang/18/lib:libs": { + "type": "glob", + "includes": ["*"], + }, + "third_party/llvm-build/Release+Asserts/lib/clang/18/share:share": { + "type": "glob", + "includes": ["*"], + }, + "build/linux/debian_bullseye_amd64-sysroot/lib/x86_64-linux-gnu:libso": { + "type": "glob", + "includes": ["*.so*"], + }, + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu:libs": { + "type": "glob", + "includes": ["*.o", "*.so*", "lib*.a"], + }, + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu:libgcc": { + "type": "glob", + "includes": ["*.o", "*.a", "*.so"], + }, } + if android.enabled(ctx): + for arch in android_archs: + for ver in android_versions: + group = "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/%s/%d:link" % (arch, ver) + fg[group] = { + "type": "glob", + "includes": ["*"], + } + fg.update(clang_all.filegroups(ctx)) return fg @@ -62,6 +106,23 @@ def __step_config(ctx, step_config): "build/linux/debian_bullseye_i386-sysroot/usr/include:include", "build/linux/debian_bullseye_i386-sysroot/usr/lib:headers", ], + "build/linux/debian_bullseye_amd64-sysroot:link": [ + "build/linux/debian_bullseye_amd64-sysroot/lib/x86_64-linux-gnu:libso", + "build/linux/debian_bullseye_amd64-sysroot/lib64/ld-linux-x86-64.so.2", + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/gcc/x86_64-linux-gnu:libgcc", + "build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu:libs", + "third_party/llvm-build/Release+Asserts/bin/clang", + "third_party/llvm-build/Release+Asserts/bin/clang++", + "third_party/llvm-build/Release+Asserts/bin/ld.lld", + "third_party/llvm-build/Release+Asserts/bin/lld", + "third_party/llvm-build/Release+Asserts/bin/llvm-nm", + "third_party/llvm-build/Release+Asserts/bin/llvm-readelf", + "third_party/llvm-build/Release+Asserts/bin/llvm-readobj", + # The following inputs are used for sanitizer builds. + # It might be better to add them only for sanitizer builds if there is a performance issue. + "third_party/llvm-build/Release+Asserts/lib/clang/18/lib:libs", + "third_party/llvm-build/Release+Asserts/lib/clang/18/share:share", + ], "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot:headers": [ "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include:include", "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/local/include:include", @@ -120,6 +181,52 @@ def __step_config(ctx, step_config): "timeout": "2m", }, ]) + + # TODO: b/316267242 - Enable remote links for Android and CrOS toolchain builds. + if not android.enabled(ctx) and not (cros.custom_toolchain(ctx) or cros.custom_sysroot(ctx)): + step_config["rules"].extend([ + { + "name": "clang/alink/llvm-ar", + "action": "(.*_)?alink", + "inputs": [ + # TODO: b/316267242 - Add inputs to GN config. + "third_party/llvm-build/Release+Asserts/bin/llvm-ar", + ], + "exclude_input_patterns": [ + "*.cc", + "*.h", + "*.js", + "*.pak", + "*.py", + "*.stamp", + ], + "remote": config.get(ctx, "remote-library-link"), + "platform_ref": "large", + "accumulate": True, + }, + { + "name": "clang/solink/gcc_solink_wrapper", + "action": "(.*_)?solink", + "command_prefix": "\"python3\" \"../../build/toolchain/gcc_solink_wrapper.py\"", + "inputs": [ + # TODO: b/316267242 - Add inputs to GN config. + "build/toolchain/gcc_solink_wrapper.py", + "build/toolchain/whole_archive.py", + "build/toolchain/wrapper_utils.py", + "build/linux/debian_bullseye_amd64-sysroot:link", + ], + "exclude_input_patterns": [ + "*.cc", + "*.h", + "*.js", + "*.pak", + "*.py", + "*.stamp", + ], + "remote": config.get(ctx, "remote-library-link"), + "platform_ref": "large", + }, + ]) return step_config clang = module( diff --git a/naiveproxy/src/build/config/siso/clang_mac.star b/naiveproxy/src/build/config/siso/clang_mac.star index 7195eed1a5..1c21a1a556 100644 --- a/naiveproxy/src/build/config/siso/clang_mac.star +++ b/naiveproxy/src/build/config/siso/clang_mac.star @@ -4,6 +4,7 @@ # found in the LICENSE file. """Siso configuration for clang/mac.""" +load("@builtin//lib/gn.star", "gn") load("@builtin//path.star", "path") load("@builtin//struct.star", "module") load("./clang_all.star", "clang_all") @@ -11,23 +12,43 @@ load("./clang_code_coverage_wrapper.star", "clang_code_coverage_wrapper") load("./rewrapper_cfg.star", "rewrapper_cfg") def __filegroups(ctx): + sdk_includes = [ + "*.framework", + "*.h", + "*.json", + "*.modulemap", + "Current", + "Frameworks", + "Headers", + "Modules", + "crt*.o", + "usr/include/c++/v1/*", + "usr/include/c++/v1/*/*", + ] fg = { "build/mac_files/xcode_binaries/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk:headers": { "type": "glob", - "includes": [ - "*.h", - "*.json", - "*.modulemap", - "Current", - "Frameworks", - "Headers", - "Modules", - "crt*.o", - "usr/include/c++/v1/*", - "usr/include/c++/v1/*/*", - ], + "includes": sdk_includes, }, } + + # precompute subtree for sysroot/frameworks for siso scandeps, + # which is not complex enough to handle C preprocessor tricks + # and need system include dirs when using deps log of -MMD. + # need to add new entries when new version is used. + # TODO: b/323091468 - get sysroot, ios_sdk_path from gn + fg[ctx.fs.canonpath("./sdk/xcode_links/MacOSX14.2.sdk") + ":headers"] = { + "type": "glob", + "includes": sdk_includes, + } + fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator17.2.sdk") + ":headers"] = { + "type": "glob", + "includes": sdk_includes, + } + fg[ctx.fs.canonpath("./sdk/xcode_links/iPhoneSimulator.platform/Developer/Library/Frameworks") + ":headers"] = { + "type": "glob", + "includes": sdk_includes, + } fg.update(clang_all.filegroups(ctx)) return fg @@ -43,10 +64,26 @@ def __step_config(ctx, step_config): cfg = "buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_mac.cfg" if ctx.fs.exists(cfg): reproxy_config = rewrapper_cfg.parse(ctx, cfg) + largePlatform = {} + for k, v in reproxy_config["platform"].items(): + if k.startswith("label:action"): + continue + largePlatform[k] = v + largePlatform["label:action_large"] = "1" step_config["platforms"].update({ "clang": reproxy_config["platform"], + "clang_large": largePlatform, }) step_config["input_deps"].update(clang_all.input_deps) + + # TODO: https://issues.chromium.org/40120210 - remove this + # once we can use relative path in hmap. + need_input_root_absolute_path_for_objc = False + gn_args = gn.args(ctx) + if gn_args.get("target_os") == "\"ios\"": + # objc/objcxx uses hmap, which contains absolute path + # see also b/256536089 + need_input_root_absolute_path_for_objc = True step_config["rules"].extend([ { "name": "clang/cxx", @@ -74,6 +111,7 @@ def __step_config(ctx, step_config): "platform_ref": "clang", "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], + "input_root_absolute_path": need_input_root_absolute_path_for_objc, }, { "name": "clang/objc", @@ -83,6 +121,7 @@ def __step_config(ctx, step_config): "platform_ref": "clang", "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], + "input_root_absolute_path": need_input_root_absolute_path_for_objc, }, { "name": "clang-coverage/cxx", @@ -122,6 +161,7 @@ def __step_config(ctx, step_config): "platform_ref": "clang", "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], + "input_root_absolute_path": need_input_root_absolute_path_for_objc, }, { "name": "clang-coverage/objc", @@ -135,6 +175,7 @@ def __step_config(ctx, step_config): "platform_ref": "clang", "remote": True, "remote_wrapper": reproxy_config["remote_wrapper"], + "input_root_absolute_path": need_input_root_absolute_path_for_objc, }, ]) return step_config diff --git a/naiveproxy/src/build/config/siso/clang_windows.star b/naiveproxy/src/build/config/siso/clang_windows.star index b22f03f3aa..9f8dc03759 100644 --- a/naiveproxy/src/build/config/siso/clang_windows.star +++ b/naiveproxy/src/build/config/siso/clang_windows.star @@ -56,8 +56,15 @@ def __step_config(ctx, step_config): cfg = "buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_windows.cfg" if ctx.fs.exists(cfg): reproxy_config = rewrapper_cfg.parse(ctx, cfg) + largePlatform = {} + for k, v in reproxy_config["platform"].items(): + if k.startswith("label:action"): + continue + largePlatform[k] = v + largePlatform["label:action_large"] = "1" step_config["platforms"].update({ "clang-cl": reproxy_config["platform"], + "clang-cl_large": largePlatform, }) step_config["input_deps"].update(clang_all.input_deps) diff --git a/naiveproxy/src/build/config/siso/config.star b/naiveproxy/src/build/config/siso/config.star index 562cec7f4d..422345c73b 100644 --- a/naiveproxy/src/build/config/siso/config.star +++ b/naiveproxy/src/build/config/siso/config.star @@ -12,6 +12,9 @@ __KNOWN_CONFIG_OPTIONS = [ # TODO: b/308405411 - Enable this config for all builders. "remote-devtools-frontend-typescript", + + # TODO: b/316267242 - Enable remote links after confirming performance. + "remote-library-link", ] def __check(ctx): diff --git a/naiveproxy/src/build/config/siso/cros.star b/naiveproxy/src/build/config/siso/cros.star index b33a094542..6b95e04eaa 100644 --- a/naiveproxy/src/build/config/siso/cros.star +++ b/naiveproxy/src/build/config/siso/cros.star @@ -8,31 +8,51 @@ load("@builtin//lib/gn.star", "gn") load("@builtin//path.star", "path") load("@builtin//struct.star", "module") -def __filegroups(ctx): - fg = {} +def __custom_toolchain(ctx): if not "args.gn" in ctx.metadata: print("no args.gn") - return fg + return None gn_args = gn.args(ctx) + if gn_args.get("target_os") != '"chromeos"': + return None if not "cros_target_cxx" in gn_args: print("no cros_target_cxx") - return fg - toolchain = gn_args.get("cros_target_cxx") - toolchain = toolchain.strip('"') - toolchain = ctx.fs.canonpath(toolchain) + return None + cros_target_cxx = gn_args.get("cros_target_cxx") + cros_target_cxx = cros_target_cxx.strip('"') + cros_target_cxx = ctx.fs.canonpath(cros_target_cxx) + toolchain = path.dir(path.dir(cros_target_cxx)) + if not toolchain: + fail("failed to detect cros custom toolchain. cros_target_cxx = %s" % gn_args.get("cros_target_cxx")) + return toolchain + +def __custom_sysroot(ctx): + if not "args.gn" in ctx.metadata: + print("no args.gn") + return None + gn_args = gn.args(ctx) + if gn_args.get("target_os") != '"chromeos"': + return None + if not "target_sysroot" in gn_args: + print("no target_sysroot") + return None + sysroot = gn_args.get("target_sysroot") + sysroot = sysroot.strip('"') + sysroot = ctx.fs.canonpath(sysroot) + if not sysroot: + fail("failed to detect cros custom sysroot. target_sysroot = %s" % gn_args.get("target_sysroot")) + return sysroot + +def __filegroups(ctx): + fg = {} + toolchain = __custom_toolchain(ctx) print("toolchain = %s" % toolchain) if toolchain: - toolchain = path.dir(path.dir(toolchain)) fg[toolchain + ":headers"] = { "type": "glob", "includes": ["*"], } - if not "target_sysroot" in gn_args: - print("no target_sysroot") - return fg - sysroot = gn_args.get("target_sysroot") - sysroot = sysroot.strip('"') - sysroot = ctx.fs.canonpath(sysroot) + sysroot = __custom_sysroot(ctx) print("sysroot = %s" % sysroot) if sysroot: fg[path.join(sysroot, "usr/include") + ":include"] = { @@ -68,48 +88,42 @@ __handlers = { } def __step_config(ctx, step_config): - if not "args.gn" in ctx.metadata: - return step_config - gn_args = gn.args(ctx) - if "cros_target_cxx" in gn_args: - toolchain = gn_args.get("cros_target_cxx") - if toolchain: - step_config["rules"].extend([ - { - "name": "clang-cros/cxx", - "action": "(.*_)?cxx", - "command_prefix": "../../build/cros_cache/chrome-sdk/", - "remote": True, - "handler": "cros_compiler", - "canonicalize_dir": True, - "timeout": "5m", - }, - { - "name": "clang-cros/cc", - "action": "(.*_)?cc", - "command_prefix": "../../build/cros_cache/chrome-sdk/", - "remote": True, - "handler": "cros_compiler", - "canonicalize_dir": True, - "timeout": "5m", - }, - ]) - if "target_sysroot" in gn_args: - sysroot = gn_args.get("target_sysroot") - if sysroot: - sysroot = sysroot.strip('"') - sysroot = ctx.fs.canonpath(sysroot) - step_config["input_deps"].update({ - sysroot + ":headers": [ - path.join(sysroot, "usr/include") + ":include", - path.join(sysroot, "usr/lib") + ":headers", - path.join(sysroot, "usr/lib64") + ":headers", - ], - }) + if __custom_toolchain(ctx): + step_config["rules"].extend([ + { + "name": "clang-cros/cxx", + "action": "(.*_)?cxx", + "command_prefix": "../../build/cros_cache/chrome-sdk/", + "remote": True, + "handler": "cros_compiler", + "canonicalize_dir": True, + "timeout": "5m", + }, + { + "name": "clang-cros/cc", + "action": "(.*_)?cc", + "command_prefix": "../../build/cros_cache/chrome-sdk/", + "remote": True, + "handler": "cros_compiler", + "canonicalize_dir": True, + "timeout": "5m", + }, + ]) + sysroot = __custom_sysroot(ctx) + if sysroot: + step_config["input_deps"].update({ + sysroot + ":headers": [ + path.join(sysroot, "usr/include") + ":include", + path.join(sysroot, "usr/lib") + ":headers", + path.join(sysroot, "usr/lib64") + ":headers", + ], + }) return step_config cros = module( "cros", + custom_toolchain = __custom_toolchain, + custom_sysroot = __custom_sysroot, filegroups = __filegroups, handlers = __handlers, step_config = __step_config, diff --git a/naiveproxy/src/build/config/siso/linux.star b/naiveproxy/src/build/config/siso/linux.star index 30675164a0..9969dac7e6 100644 --- a/naiveproxy/src/build/config/siso/linux.star +++ b/naiveproxy/src/build/config/siso/linux.star @@ -47,10 +47,13 @@ def __step_config(ctx, step_config): if android.enabled(ctx): step_config = android.step_config(ctx, step_config) + # nacl step config should be added before clang step config for link step + # rules. + step_config = nacl.step_config(ctx, step_config) + step_config = clang.step_config(ctx, step_config) step_config = cros.step_config(ctx, step_config) step_config = devtools_frontend.step_config(ctx, step_config) - step_config = nacl.step_config(ctx, step_config) step_config = nasm.step_config(ctx, step_config) step_config = proto.step_config(ctx, step_config) step_config = rust.step_config(ctx, step_config) diff --git a/naiveproxy/src/build/config/siso/mac.star b/naiveproxy/src/build/config/siso/mac.star index 86b31c6387..e50b3acf86 100644 --- a/naiveproxy/src/build/config/siso/mac.star +++ b/naiveproxy/src/build/config/siso/mac.star @@ -15,12 +15,29 @@ def __filegroups(ctx): fg.update(typescript.filegroups(ctx)) return fg -__handlers = {} +# to reduce unnecessary local process and +# unnecessary digest calculation of output file. +def __copy_bundle_data(ctx, cmd): + input = cmd.inputs[0] + out = cmd.outputs[0] + ctx.actions.copy(input, out, recursive = ctx.fs.is_dir(input)) + ctx.actions.exit(exit_status = 0) + +__handlers = { + "copy_bundle_data": __copy_bundle_data, +} __handlers.update(clang.handlers) __handlers.update(typescript.handlers) def __step_config(ctx, step_config): config.check(ctx) + step_config["rules"].extend([ + { + "name": "mac/copy_bundle_data", + "action": "(.*)?copy_bundle_data", + "handler": "copy_bundle_data", + }, + ]) step_config = clang.step_config(ctx, step_config) step_config = typescript.step_config(ctx, step_config) return step_config diff --git a/naiveproxy/src/build/config/siso/main.star b/naiveproxy/src/build/config/siso/main.star index 7df262749f..18d2d127b6 100644 --- a/naiveproxy/src/build/config/siso/main.star +++ b/naiveproxy/src/build/config/siso/main.star @@ -20,47 +20,109 @@ def __use_large_b289968566(ctx, step_config): # TODO(b/289968566): they often faile with exit=137 (OOM?). # They need to run on a machine has more memory than the default machine type n2-custom-2-3840 exit137_list = [ + "./android_clang_arm/obj/content/browser/browser/browser_interface_binders.o", "./android_clang_arm/obj/third_party/distributed_point_functions/distributed_point_functions/evaluate_prg_hwy.o", "./ash_clang_x64/obj/chrome/browser/ash/ash/autotest_private_api.o", "./ash_clang_x64/obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", + "./ash_clang_x64/obj/chrome/browser/ash/ash/user_session_manager.o", "./ash_clang_x64/obj/chrome/browser/browser/browser_prefs.o", "./ash_clang_x64/obj/chrome/browser/browser/chrome_browser_interface_binders.o", + "./ash_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", + "./ash_clang_x64/obj/chrome/test/test_support_ui/offer_notification_bubble_views_test_base.o", + "./ash_clang_x64/obj/chrome/test/test_support_ui/web_app_integration_test_driver.o", + "./ash_clang_x64/obj/content/browser/browser/browser_interface_binders.o", + "./lacros_clang_x64/obj/chrome/browser/browser/chrome_content_browser_client.o", + "./lacros_clang_x64/obj/content/browser/browser/browser_interface_binders.o", + "./obj/ash_clang_x64/chrome/test/test_support_ui/offer_notification_bubble_views_test_base.o", "./obj/chrome/browser/ash/ash/autotest_private_api.o", "./obj/chrome/browser/ash/ash/chrome_browser_main_parts_ash.o", + "./obj/chrome/browser/ash/ash/user_session_manager.o", + "./obj/chrome/browser/ash/ash/webui_login_view.o", + "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/media_app_integration_browsertest.o", "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/personalization_app_time_of_day_browsertest.o", "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/personalization_app_wallpaper_daily_refresh_browsertest.o", + "./obj/chrome/browser/ash/system_web_apps/apps/browser_tests/projector_app_integration_browsertest.o", "./obj/chrome/browser/ash/system_web_apps/browser_tests/system_web_app_manager_browsertest.o", + "./obj/chrome/browser/ash/test_support/oobe_screens_utils.o", "./obj/chrome/browser/ash/unit_tests/wizard_controller_unittest.o", "./obj/chrome/browser/autofill/interactive_ui_tests/autofill_interactive_uitest.o", "./obj/chrome/browser/browser/browser_prefs.o", "./obj/chrome/browser/browser/chrome_browser_interface_binders.o", "./obj/chrome/browser/browser/chrome_content_browser_client.o", "./obj/chrome/browser/ui/ash/holding_space/browser_tests/holding_space_ui_browsertest.o", + "./obj/chrome/browser/web_applications/web_applications_browser_tests/isolated_web_app_policy_manager_ash_browsertest.o", "./obj/chrome/test/browser_tests/app_list_client_impl_browsertest.o", + "./obj/chrome/test/browser_tests/ash_hud_login_browsertest.o", + "./obj/chrome/test/browser_tests/assistant_optin_flow_screen_browsertest.o", + "./obj/chrome/test/browser_tests/autotest_private_apitest.o", "./obj/chrome/test/browser_tests/browser_non_client_frame_view_browsertest.o", "./obj/chrome/test/browser_tests/browser_non_client_frame_view_chromeos_browsertest.o", "./obj/chrome/test/browser_tests/capture_mode_browsertest.o", "./obj/chrome/test/browser_tests/chrome_shelf_controller_browsertest.o", + "./obj/chrome/test/browser_tests/configuration_based_oobe_browsertest.o", + "./obj/chrome/test/browser_tests/consolidated_consent_screen_browsertest.o", + "./obj/chrome/test/browser_tests/consumer_update_screen_browsertest.o", + "./obj/chrome/test/browser_tests/demo_setup_browsertest.o", "./obj/chrome/test/browser_tests/device_local_account_browsertest.o", + "./obj/chrome/test/browser_tests/devtools_browsertest.o", + "./obj/chrome/test/browser_tests/display_size_screen_browsertest.o", + "./obj/chrome/test/browser_tests/drive_pinning_screen_browsertest.o", + "./obj/chrome/test/browser_tests/enrollment_embedded_policy_server_browsertest.o", + "./obj/chrome/test/browser_tests/enterprise_remote_apps_apitest.o", + "./obj/chrome/test/browser_tests/error_screen_browsertest.o", + "./obj/chrome/test/browser_tests/existing_user_controller_browsertest.o", "./obj/chrome/test/browser_tests/file_manager_browsertest_base.o", + "./obj/chrome/test/browser_tests/file_manager_policy_browsertest.o", "./obj/chrome/test/browser_tests/file_tasks_browsertest.o", "./obj/chrome/test/browser_tests/full_restore_app_launch_handler_browsertest.o", + "./obj/chrome/test/browser_tests/hid_detection_screen_browsertest.o", + "./obj/chrome/test/browser_tests/kiosk_browsertest.o", + "./obj/chrome/test/browser_tests/lacros_data_migration_screen_browsertest.o", "./obj/chrome/test/browser_tests/login_browsertest.o", + "./obj/chrome/test/browser_tests/login_manager_test.o", "./obj/chrome/test/browser_tests/login_ui_browsertest.o", + "./obj/chrome/test/browser_tests/login_ui_shelf_visibility_browsertest.o", + "./obj/chrome/test/browser_tests/management_transition_screen_browsertest.o", + "./obj/chrome/test/browser_tests/marketing_opt_in_screen_browsertest.o", + "./obj/chrome/test/browser_tests/metadata_processor_ash_browsertest.o", + "./obj/chrome/test/browser_tests/minimum_version_policy_handler_browsertest.o", + "./obj/chrome/test/browser_tests/notification_display_client_browsertest.o", + "./obj/chrome/test/browser_tests/oauth2_browsertest.o", + "./obj/chrome/test/browser_tests/offline_login_test_mixin.o", + "./obj/chrome/test/browser_tests/oobe_base_test.o", + "./obj/chrome/test/browser_tests/oobe_browsertest.o", + "./obj/chrome/test/browser_tests/oobe_interactive_ui_test.o", + "./obj/chrome/test/browser_tests/oobe_metrics_browsertest.o", + "./obj/chrome/test/browser_tests/policy_certs_browsertest.o", "./obj/chrome/test/browser_tests/pwa_install_view_browsertest.o", + "./obj/chrome/test/browser_tests/quick_start_screen_browsertest.o", "./obj/chrome/test/browser_tests/remote_apps_manager_browsertest.o", "./obj/chrome/test/browser_tests/safe_browsing_blocking_page_test.o", "./obj/chrome/test/browser_tests/save_card_bubble_views_browsertest.o", "./obj/chrome/test/browser_tests/scalable_iph_browsertest.o", + "./obj/chrome/test/browser_tests/session_login_browsertest.o", "./obj/chrome/test/browser_tests/spoken_feedback_browsertest.o", + "./obj/chrome/test/browser_tests/sync_consent_browsertest.o", + "./obj/chrome/test/browser_tests/theme_selection_screen_browsertest.o", + "./obj/chrome/test/browser_tests/touchpad_scroll_screen_browsertest.o", + "./obj/chrome/test/browser_tests/update_screen_browsertest.o", + "./obj/chrome/test/browser_tests/usertype_by_devicetype_metrics_provider_browsertest.o", + "./obj/chrome/test/browser_tests/web_view_browsertest.o", "./obj/chrome/test/browser_tests/webview_login_browsertest.o", + "./obj/chrome/test/browser_tests/welcome_screen_browsertest.o", + "./obj/chrome/test/browser_tests/wizard_controller_browsertest.o", "./obj/chrome/test/interactive_ui_tests/iban_bubble_view_uitest.o", "./obj/chrome/test/interactive_ui_tests/local_card_migration_uitest.o", + "./obj/chrome/test/interactive_ui_tests/login_manager_test.o", "./obj/chrome/test/interactive_ui_tests/system_web_app_interactive_uitest.o", + "./obj/chrome/test/interactive_ui_tests/tab_drag_controller_interactive_uitest.o", "./obj/chrome/test/test_support_ui/offer_notification_bubble_views_test_base.o", + "./obj/chrome/test/test_support_ui/web_app_integration_test_driver.o", "./obj/chrome/test/unit_tests/chrome_browsing_data_remover_delegate_unittest.o", + "./obj/chrome/test/unit_tests/chrome_shelf_controller_unittest.o", "./obj/chrome/test/unit_tests/site_settings_handler_unittest.o", "./obj/content/browser/browser/browser_interface_binders.o", + "./obj/fuchsia_web/runners/cast_runner_exe/main.o", "./obj/fuchsia_web/runners/cast_runner_integration_tests__exec/cast_runner_integration_test.o", "./obj/fuchsia_web/webengine/web_engine_core/frame_impl.o", ] @@ -78,7 +140,13 @@ def __use_large_b289968566(ctx, step_config): r.update(rule) r["name"] += "/b289968566/exit-137" r["action_outs"] = exit137_list - r["platform_ref"] = "large" + + # use `_large` variant of platform if it doesn't use default platform, + # i.e. mac/win case. + if "platform_ref" in r: + r["platform_ref"] = r["platform_ref"] + "_large" + else: + r["platform_ref"] = "large" if r.get("handler") == "rewrite_rewrapper": r["handler"] = "rewrite_rewrapper_large" new_rules.append(r) diff --git a/naiveproxy/src/build/config/siso/nacl_linux.star b/naiveproxy/src/build/config/siso/nacl_linux.star index e296d016f1..f6ee6e517b 100644 --- a/naiveproxy/src/build/config/siso/nacl_linux.star +++ b/naiveproxy/src/build/config/siso/nacl_linux.star @@ -51,6 +51,7 @@ __handlers = {} def __step_config(ctx, step_config): step_config["rules"].extend([ + # pnacl { "name": "nacl/pnacl-clang++", "action": "newlib_pnacl.*_cxx", @@ -85,6 +86,12 @@ def __step_config(ctx, step_config): "remote": False, "input_root_absolute_path": True, }, + { + "name": "nacl/pnacl-ar", + "action": "newlib_pnacl_alink", + "remote": False, + }, + # glibc { "name": "nacl/glibc/x86_64-nacl-g++", "action": "glibc_x64_cxx", @@ -92,11 +99,21 @@ def __step_config(ctx, step_config): "native_client/toolchain/linux_x86/nacl_x86_glibc/bin/x86_64-nacl-g++", ], # ELF-32 doesn't work on gVisor, - # so will local-fallback if gVisor is used. - # TODO(b/278485912): remote=True for trusted instance. "remote": False, - "input_root_absolute_path": True, }, + { + "name": "nacl/glibc/x86_64-nacl-ar", + "action": "glibc_x64_alink", + # ELF-32 doesn't work on gVisor, + "remote": False, + }, + { + "name": "nacl/glibc/x86_64_solink/gcc_solink_wrapper", + "action": "glibc_x64_solink", + # ELF-32 doesn't work on gVisor, + "remote": False, + }, + # pnacl_newlib { "name": "nacl/pnacl_newlib/x86_64-nacl-clang++", "action": "clang_newlib_x64_cxx", @@ -119,6 +136,12 @@ def __step_config(ctx, step_config): "input_root_absolute_path": True, "timeout": "2m", }, + { + "name": "nacl/pnacl_newlib/x86_64-nacl-ar", + "action": "clang_newlib_x64_alink", + "remote": False, + }, + # saigo_newlib { "name": "nacl/saigo_newlib/x86_64-nacl-clang++", "action": "irt_x64_cxx", @@ -141,6 +164,11 @@ def __step_config(ctx, step_config): "input_root_absolute_path": True, "timeout": "2m", }, + { + "name": "nacl/saigo_newlib/x86_64-nacl-ar", + "action": "(.*_)?irt_x64_alink", + "remote": False, + }, ]) step_config["input_deps"].update({ diff --git a/naiveproxy/src/build/config/siso/reproxy.star b/naiveproxy/src/build/config/siso/reproxy.star index 7a78208a1e..383f417171 100644 --- a/naiveproxy/src/build/config/siso/reproxy.star +++ b/naiveproxy/src/build/config/siso/reproxy.star @@ -283,11 +283,13 @@ def __step_config(ctx, step_config): new_rules.append(new_rule) continue - # clang will always have rewrapper config when use_remoteexec=true. + # clang cxx/cc/objcxx/objc will always have rewrapper config when use_remoteexec=true. # Remove the native siso handling and replace with custom rewrapper-specific handling. # All other rule values are not reused, instead use rewrapper config via handler. # (In particular, command_prefix should be avoided because it will be rewrapper.) - if rule["name"].startswith("clang/") or rule["name"].startswith("clang-cl/"): + if (rule["name"].startswith("clang/cxx") or rule["name"].startswith("clang/cc") or + rule["name"].startswith("clang-cl/cxx") or rule["name"].startswith("clang-cl/cc") or + rule["name"].startswith("clang/objc")): if not rule.get("action"): fail("clang rule %s found without action" % rule["name"]) @@ -296,6 +298,7 @@ def __step_config(ctx, step_config): "action": rule["action"], "exclude_input_patterns": rule.get("exclude_input_patterns"), "handler": "rewrite_rewrapper", + "input_root_absolute_path": rule.get("input_root_absolute_path"), } new_rules.append(new_rule) continue diff --git a/naiveproxy/src/build/config/siso/rust_linux.star b/naiveproxy/src/build/config/siso/rust_linux.star index a59c760830..bdfc9aeee0 100644 --- a/naiveproxy/src/build/config/siso/rust_linux.star +++ b/naiveproxy/src/build/config/siso/rust_linux.star @@ -13,6 +13,8 @@ def __filegroups(ctx): "includes": [ "bin/rustc", "lib/*.so", + "lib/rustlib/src/rust/library/std/src/lib.rs", + "lib/rustlib/x86_64-unknown-linux-gnu/lib/*", ], }, "build/linux/debian_bullseye_amd64-sysroot:rustlink": { @@ -49,12 +51,29 @@ def __filegroups(ctx): def __rust_bin_handler(ctx, cmd): inputs = [] + use_android_toolchain = None + target = None for i, arg in enumerate(cmd.args): if arg.startswith("--sysroot=../../third_party/fuchsia-sdk/sdk/arch/x64/sysroot"): inputs.extend([ "third_party/fuchsia-sdk/sdk/arch/x64/lib:rustlink", "third_party/fuchsia-sdk/sdk/arch/x64/sysroot:rustlink", ]) + elif arg.startswith("--sysroot=../../third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot"): + use_android_toolchain = True + if arg.startswith("--target="): + target = arg.removeprefix("--target=") + if use_android_toolchain and target: + # e.g. target=aarch64-linux-android26 + android_ver = "" + i = target.find("android") + if i >= 0: + android_ver = target[i:].removeprefix("android").removeprefix("eabi") + if android_ver: + android_arch = target.removesuffix(android_ver) + filegroup = "third_party/android_toolchain/ndk/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/%s/%s:link" % (android_arch, android_ver) + inputs.append(filegroup) + ctx.actions.fix(inputs = cmd.inputs + inputs) __handlers = { diff --git a/naiveproxy/src/build/config/siso/tsc.star b/naiveproxy/src/build/config/siso/tsc.star index dad490468c..e61ff48b2a 100644 --- a/naiveproxy/src/build/config/siso/tsc.star +++ b/naiveproxy/src/build/config/siso/tsc.star @@ -13,12 +13,6 @@ def _load(ctx, tsconfig_path, loaded): def _paths(ctx, tsconfig_path, tsconfig, loaded): paths = [tsconfig_path] tsconfig_dir = path.dir(tsconfig_path) - if "extends" in tsconfig and tsconfig["extends"]: - base = path.join(tsconfig_dir, tsconfig["extends"]) - paths.append(base) - parent = _load(ctx, base, loaded) - if "files" in parent and not tsconfig["files"]: - tsconfig["files"] = parent["files"] if "files" in tsconfig: for file in tsconfig["files"]: paths.append(path.join(tsconfig_dir, file)) @@ -36,15 +30,18 @@ def _scan_inputs(ctx, tsconfig_path, tsconfig, loaded, scanned): for fname in _paths(ctx, tsconfig_path, tsconfig, loaded): if fname not in inputs: inputs[fname] = True - if "references" in tsconfig: - for ref in tsconfig["references"]: - refname = path.join(path.dir(tsconfig_path), ref["path"]) - if refname not in inputs: - inputs[refname] = True - reftc = _load(ctx, refname, loaded) - for fname in _scan_inputs(ctx, refname, reftc, loaded, scanned): - if fname not in inputs: - inputs[fname] = True + tsconfig_dir = path.dir(tsconfig_path) + tsconfig_deps = [ref["path"] for ref in tsconfig.get("references", [])] + if "extends" in tsconfig: + tsconfig_deps.append(tsconfig["extends"]) + for tsconfig_dep in tsconfig_deps: + ref_path = path.join(tsconfig_dir, tsconfig_dep) + if ref_path not in inputs: + inputs[ref_path] = True + ref_tsconfig = _load(ctx, ref_path, loaded) + for fname in _scan_inputs(ctx, ref_path, ref_tsconfig, loaded, scanned): + if fname not in inputs: + inputs[fname] = True scanned[tsconfig_path] = inputs.keys() return scanned[tsconfig_path] diff --git a/naiveproxy/src/build/config/win/BUILD.gn b/naiveproxy/src/build/config/win/BUILD.gn index 6e1417aa40..39da640443 100644 --- a/naiveproxy/src/build/config/win/BUILD.gn +++ b/naiveproxy/src/build/config/win/BUILD.gn @@ -420,6 +420,7 @@ config("delayloads") { "/DELAYLOAD:credui.dll", "/DELAYLOAD:cryptui.dll", "/DELAYLOAD:d3d11.dll", + "/DELAYLOAD:d3d12.dll", "/DELAYLOAD:d3d9.dll", "/DELAYLOAD:dwmapi.dll", "/DELAYLOAD:dxgi.dll", @@ -615,17 +616,9 @@ config("static_crt") { # Subsystem -------------------------------------------------------------------- # This is appended to the subsystem to specify a minimum version. -if (current_cpu == "x64") { - # The number after the comma is the minimum required OS version. - # 5.02 = Windows Server 2003. - subsystem_version_suffix = ",5.02" -} else if (current_cpu == "arm64") { - # Windows ARM64 requires Windows 10. - subsystem_version_suffix = ",10.0" -} else { - # 5.01 = Windows XP. - subsystem_version_suffix = ",5.01" -} +# The number after the comma is the minimum required OS version. +# Set to 10.0 since we only support >= Win10 since M110. +subsystem_version_suffix = ",10.0" config("console") { ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ] diff --git a/naiveproxy/src/build/extract_partition.py b/naiveproxy/src/build/extract_partition.py index 319ce8fc7f..5b8267a3f5 100755 --- a/naiveproxy/src/build/extract_partition.py +++ b/naiveproxy/src/build/extract_partition.py @@ -6,7 +6,6 @@ import argparse import hashlib -import math import os import struct import subprocess @@ -73,16 +72,11 @@ def _ExtractPartition(objcopy, input_elf, output_elf, partition): old_build_id_file = os.path.join(tempdir, 'old_build_id') new_build_id_file = os.path.join(tempdir, 'new_build_id') - # Dump out build-id section and remove original build-id section from - # ELF file. + # Dump out build-id section. subprocess.check_call([ objcopy, '--extract-partition', partition, - # Note: Not using '--update-section' here as it is not supported - # by llvm-objcopy. - '--remove-section', - build_id_section, '--dump-section', '{}={}'.format(build_id_section, old_build_id_file), input_elf, @@ -112,15 +106,11 @@ def _ExtractPartition(objcopy, input_elf, output_elf, partition): with open(new_build_id_file, 'wb') as f: f.write(prefix + _ComputeNewBuildId(build_id, output_elf)) - # Write back the new build-id section. + # Update the build-id section. subprocess.check_call([ objcopy, - '--add-section', + '--update-section', '{}={}'.format(build_id_section, new_build_id_file), - # Add alloc section flag, or else the section will be removed by - # objcopy --strip-all when generating unstripped lib file. - '--set-section-flags', - '{}={}'.format(build_id_section, 'alloc'), temp_elf, output_elf, ]) diff --git a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 index a7189f7f9d..1e9239692e 100644 --- a/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 +++ b/naiveproxy/src/build/fuchsia/linux_internal.sdk.sha1 @@ -1 +1 @@ -17.20240119.2.1 +18.20240217.1.1 diff --git a/naiveproxy/src/build/fuchsia/test/ffx_emulator.py b/naiveproxy/src/build/fuchsia/test/ffx_emulator.py index 3a26bb987d..d07e852096 100644 --- a/naiveproxy/src/build/fuchsia/test/ffx_emulator.py +++ b/naiveproxy/src/build/fuchsia/test/ffx_emulator.py @@ -9,15 +9,12 @@ import logging import os import json import random -import subprocess from contextlib import AbstractContextManager from common import run_ffx_command, IMAGES_ROOT, INTERNAL_IMAGES_ROOT, SDK_ROOT from compatible_utils import get_host_arch -_EMU_COMMAND_RETRIES = 3 - class FfxEmulator(AbstractContextManager): """A helper for managing emulators.""" @@ -116,24 +113,15 @@ class FfxEmulator(AbstractContextManager): qemu_arm64_meta = data.replace(r'tools/x64', 'tools/arm64') with open(qemu_arm64_meta_file, "w+") as f: json.dump(ast.literal_eval(qemu_arm64_meta), f) + + # Always use qemu for arm64 images, no matter it runs on arm64 hosts or + # x64 hosts with simulation. + if self._product.endswith('arm64'): emu_command.extend(['--engine', 'qemu']) - for i in range(_EMU_COMMAND_RETRIES): - - # If the ffx daemon fails to establish a connection with - # the emulator after 85 seconds, that means the emulator - # failed to be brought up and a retry is needed. - # TODO(fxb/103540): Remove retry when start up issue is fixed. - try: - if i > 0: - logging.warning( - 'Emulator failed to start.') - run_ffx_command(cmd=emu_command, - timeout=100, - configs=['emu.start.timeout=90']) - break - except (subprocess.TimeoutExpired, subprocess.CalledProcessError): - run_ffx_command(cmd=('emu', 'stop')) + run_ffx_command(cmd=emu_command, + timeout=310, + configs=['emu.start.timeout=300']) return self._node_name diff --git a/naiveproxy/src/build/fuchsia/test/flash_device.py b/naiveproxy/src/build/fuchsia/test/flash_device.py index 41eaeff47f..c4fd13b757 100755 --- a/naiveproxy/src/build/fuchsia/test/flash_device.py +++ b/naiveproxy/src/build/fuchsia/test/flash_device.py @@ -83,12 +83,16 @@ def _run_flash_command(system_image_dir: str, target_id: Optional[str]): # This prevents multiple fastboot binaries from flashing concurrently, # which should increase the odds of flashing success. with lock(_FF_LOCK, timeout=_FF_LOCK_ACQ_TIMEOUT): + # The ffx.fastboot.inline_target has negative impact when ffx + # discovering devices in fastboot, so it's inlined here to limit its + # scope. See the discussion in https://fxbug.dev/issues/317228141. logging.info( 'Flash result %s', common.run_ffx_command(cmd=('target', 'flash', '-b', system_image_dir, '--no-bootloader-reboot'), target_id=target_id, + configs=['ffx.fastboot.inline_target=true'], capture_output=True).stdout) diff --git a/naiveproxy/src/build/fuchsia/test/isolate_daemon.py b/naiveproxy/src/build/fuchsia/test/isolate_daemon.py index 30d6dd6fad..154819e7be 100755 --- a/naiveproxy/src/build/fuchsia/test/isolate_daemon.py +++ b/naiveproxy/src/build/fuchsia/test/isolate_daemon.py @@ -38,8 +38,8 @@ class IsolateDaemon(AbstractContextManager): # Keep the alphabetical order. self._extra_inits = [ self.IsolateDir(), + ScopedFfxConfig('ffx.isolated', 'true'), ScopedFfxConfig('daemon.autostart', 'false'), - ScopedFfxConfig('discovery.zedboot.enabled', 'false'), # fxb/126212: The timeout rate determines the timeout for each file # transfer based on the size of the file / this rate (in MB). # Decreasing the rate to 1 (from 5) increases the timeout in @@ -47,13 +47,14 @@ class IsolateDaemon(AbstractContextManager): ScopedFfxConfig('fastboot.flash.timeout_rate', '1'), ScopedFfxConfig('fastboot.reboot.reconnect_timeout', '120'), ScopedFfxConfig('fastboot.usb.disabled', 'true'), - ScopedFfxConfig('ffx.fastboot.inline_target', 'true'), ScopedFfxConfig('log.level', 'debug'), ScopedFfxConfig('repository.server.listen', '"[::]:0"'), ] + (extra_inits or []) + # Updating configurations to meet the requirement of isolate. def __enter__(self): - # Updating configurations to meet the requirement of isolate. + # This environment variable needs to be set before stopping ffx daemon + # to avoid sending unnecessary analytics. os.environ['FUCHSIA_ANALYTICS_DISABLED'] = '1' stop_ffx_daemon() for extra_init in self._extra_inits: diff --git a/naiveproxy/src/build/lacros/test_runner.py b/naiveproxy/src/build/lacros/test_runner.py index 013a4877e4..9d39ec341a 100755 --- a/naiveproxy/src/build/lacros/test_runner.py +++ b/naiveproxy/src/build/lacros/test_runner.py @@ -28,12 +28,17 @@ Example usages the underlying test binary can be specified in the command. ./build/lacros/test_runner.py test out/lacros/browser_tests \\ - --ash-chrome-version=793554 + --ash-chrome-version=120.0.6099.0 The above command runs tests with a given version of ash-chrome, which is - useful to reproduce test failures, the version corresponds to the commit - position of commits on the master branch, and a list of prebuilt versions can - be found at: gs://ash-chromium-on-linux-prebuilts/x86_64. + useful to reproduce test failures. A list of prebuilt versions can + be found at: + https://chrome-infra-packages.appspot.com/p/chromium/testing/linux-ash-chromium/x86_64/ash.zip + Click on any instance, you should see the version number for that instance. + Also, there are refs, which points to the instance for that channel. It should + be close the prod version but no guarantee. + For legacy refs, like legacy119, it point to the latest version for that + milestone. ./testing/xvfb.py ./build/lacros/test_runner.py test out/lacros/browser_tests @@ -823,9 +828,9 @@ def Main(): '--ash-chrome-version', type=str, help='Version of an prebuilt ash-chrome to use for testing, for example: ' - '"793554", and the version corresponds to the commit position of commits ' - 'on the main branch. If not specified, will use the latest version ' - 'available') + '"120.0.6099.0", and the version corresponds to the commit position of ' + 'commits on the main branch. If not specified, will use the latest ' + 'version available') version_group.add_argument( '--ash-chrome-path', type=str, diff --git a/naiveproxy/src/build/linux/sysroot_scripts/sysroots.json b/naiveproxy/src/build/linux/sysroot_scripts/sysroots.json index d23c82c040..f1112b891a 100644 --- a/naiveproxy/src/build/linux/sysroot_scripts/sysroots.json +++ b/naiveproxy/src/build/linux/sysroot_scripts/sysroots.json @@ -1,49 +1,49 @@ { "bullseye_amd64": { "Key": "20230611T210420Z-2", - "Sha1Sum": "4c00ba2ad61ca7cc39392f192aa39420e086777c", + "Sha1Sum": "ec989b96c5f1e235182e5f2a5c9d23b3eb4101e0", "SysrootDir": "debian_bullseye_amd64-sysroot", "Tarball": "debian_bullseye_amd64_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_arm64": { "Key": "20230611T210420Z-2", - "Sha1Sum": "41a6c8dec4c4304d6509e30cbaf9218dffb4438e", + "Sha1Sum": "f65e4d81b81d19f4354ed1bb22afeb1f3949a446", "SysrootDir": "debian_bullseye_arm64-sysroot", "Tarball": "debian_bullseye_arm64_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_armel": { "Key": "20230611T210420Z-2", - "Sha1Sum": "bcff5c5a4060f3be7bff28aa9ff28c100b70a858", + "Sha1Sum": "e27b133d817fd141d6eacdc7db749dfaf7ae6b41", "SysrootDir": "debian_bullseye_armel-sysroot", "Tarball": "debian_bullseye_armel_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_armhf": { "Key": "20230611T210420Z-2", - "Sha1Sum": "c153bf1027a67eec0f6ea2efa190e29c9c06e603", + "Sha1Sum": "023be791a65b04d6201f2d60052742683230050b", "SysrootDir": "debian_bullseye_armhf-sysroot", "Tarball": "debian_bullseye_armhf_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_i386": { "Key": "20230611T210420Z-2", - "Sha1Sum": "cfba9004de1ace04f9604c13c30abad3be90e58f", + "Sha1Sum": "0997cb9c140089cee06252fcb656042526cdac8e", "SysrootDir": "debian_bullseye_i386-sysroot", "Tarball": "debian_bullseye_i386_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_mips64el": { "Key": "20230611T210420Z-2", - "Sha1Sum": "3ce49d1c6b5fef17ad512f2d663a175829ae0b72", + "Sha1Sum": "868d8bfdbf9bd69ea0013fed4a97fa44fbc98a21", "SysrootDir": "debian_bullseye_mips64el-sysroot", "Tarball": "debian_bullseye_mips64el_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" }, "bullseye_mipsel": { "Key": "20230611T210420Z-2", - "Sha1Sum": "1b857baabd7999ff0d6949a8973f896836ac45ac", + "Sha1Sum": "ece6684704ee0c3944f1903c39fa798ee9d7f57e", "SysrootDir": "debian_bullseye_mipsel-sysroot", "Tarball": "debian_bullseye_mipsel_sysroot.tar.xz", "URL": "https://commondatastorage.googleapis.com/chrome-linux-sysroot/toolchain" diff --git a/naiveproxy/src/build/nocompile.gni b/naiveproxy/src/build/nocompile.gni index 418e42e961..242e9104fc 100644 --- a/naiveproxy/src/build/nocompile.gni +++ b/naiveproxy/src/build/nocompile.gni @@ -65,10 +65,16 @@ if (enable_nocompile_tests) { script = "//tools/nocompile/wrapper.py" sources = invoker.sources - deps = invoker.deps + if (defined(invoker.deps)) { + deps = invoker.deps + } - # An action is not a compiler, so configs is empty until it is explicitly set. + # An action is not a compiler, so configs is empty until it is explicitly + # set. configs = default_compiler_configs + if (defined(invoker.configs)) { + configs += invoker.configs + } # Disable the checks that the Chrome style plugin normally enforces to # reduce the amount of boilerplate needed in nocompile tests. diff --git a/naiveproxy/src/build/rust/BUILD.gn b/naiveproxy/src/build/rust/BUILD.gn index c1c13bfa21..26830eedeb 100644 --- a/naiveproxy/src/build/rust/BUILD.gn +++ b/naiveproxy/src/build/rust/BUILD.gn @@ -23,8 +23,8 @@ if (toolchain_has_rust) { # on the C++ side. static_library("cxx_cppdeps") { sources = [ - "//third_party/rust/chromium_crates_io/vendor/cxx-1.0.110/include/cxx.h", - "//third_party/rust/chromium_crates_io/vendor/cxx-1.0.110/src/cxx.cc", + "//third_party/rust/chromium_crates_io/vendor/cxx-1.0.116/include/cxx.h", + "//third_party/rust/chromium_crates_io/vendor/cxx-1.0.116/src/cxx.cc", # Our version-independent forwarding header, which we patch cxx.cc to # use since we want it to use an absolute path for its include. diff --git a/naiveproxy/src/build/rust/OWNERS b/naiveproxy/src/build/rust/OWNERS index 0e7aca6e18..bb0de47abe 100644 --- a/naiveproxy/src/build/rust/OWNERS +++ b/naiveproxy/src/build/rust/OWNERS @@ -3,5 +3,4 @@ ajgo@chromium.org collinbaker@chromium.org danakj@chromium.org lukasza@chromium.org -rsesek@chromium.org thakis@chromium.org diff --git a/naiveproxy/src/build/rust/run_build_script.py b/naiveproxy/src/build/rust/run_build_script.py index fe8eb107cd..b0a0ae3cab 100755 --- a/naiveproxy/src/build/rust/run_build_script.py +++ b/naiveproxy/src/build/rust/run_build_script.py @@ -124,6 +124,12 @@ def main(): else: print(f'Invalid TARGET {env["TARGET"]}') sys.exit(1) + # See https://crbug.com/325543500 for background. + # Cargo sets CARGO_CFG_TARGET_OS to "android" even when targeting *-androideabi. + if env["CARGO_CFG_TARGET_OS"].startswith("android"): + env["CARGO_CFG_TARGET_OS"] = "android" + elif env["CARGO_CFG_TARGET_OS"] == "darwin": + env["CARGO_CFG_TARGET_OS"] = "macos" if args.features: for f in args.features: feature_name = f.upper().replace("-", "_") diff --git a/naiveproxy/src/build/rust/rust_target.gni b/naiveproxy/src/build/rust/rust_target.gni index 48d0cc31cc..439a8e98ef 100644 --- a/naiveproxy/src/build/rust/rust_target.gni +++ b/naiveproxy/src/build/rust/rust_target.gni @@ -150,9 +150,11 @@ template("rust_target") { } if (invoker.target_type == "rust_proc_macro") { - _main_target_suffix = "${target_name}__proc_macro" + _main_target_suffix = "__proc_macro" + } else if (invoker.target_type == "shared_library") { + _main_target_suffix = "__proc_macro" } else { - _main_target_suffix = "__rlib" + _main_target_suffix = "" } _deps = [] @@ -170,8 +172,6 @@ template("rust_target") { } } - _is_data_dep = defined(invoker.is_data_dep) && invoker.is_data_dep - _build_unit_tests = false if (defined(invoker.build_native_rust_unit_tests)) { _build_unit_tests = @@ -217,14 +217,13 @@ template("rust_target") { not_needed(invoker, "*") not_needed([ + "_aliased_deps", "_allow_unsafe", "_build_unit_tests", "_crate_root", "_crate_name", "_cxx_bindings", "_deps", - "_aliased_deps", - "_is_data_dep", "_rustc_metadata", "_out_dir", "_public_deps", @@ -232,46 +231,56 @@ template("rust_target") { "_rustflags", "_support_use_from_cpp", "_testonly", - "_visibility", ]) } else { + # These are dependencies that must be included into the C++ target that + # depends on this Rust one, and into the Rust target itself, respectively. + # + # For an rlib or exe, it's enough to add all these as dependencies of the + # Rust target alone, and they will get included into the final link step. + # + # But when then Rust target is a shared library, the C++ target needs to + # link the C++ thunks that are used to call the cxx bridge functions. And + # Cxx library itself needs to be in both. + _cxx_generated_deps_for_cpp = [] + _cxx_generated_deps_for_rust = [] + if (_cxx_bindings != []) { + _cxx_generated_deps_for_cpp += [ + # The Cxx-generated thunks, which have the public C++ names and bounce + # over to the Rust code. + ":${_target_name}_cxx_generated", + + # Additionally, C++ bindings generated by Cxx can include C++ types + # that come from the Cxx library, such as `rust::Str`. The header and + # implementation of these types are provided in the cxx_cppdeps target. + # The C++ targets depending on this Rust target need the headers, while + # the Rust target needs the implementation. + "//build/rust:cxx_cppdeps", + ] + _cxx_generated_deps_for_rust = [ + # The implementation of the Cxx library needs to be in the Rust target. + "//build/rust:cxx_cppdeps", + ] + } + + # Proc macros and shared libraries have a group for the target name and + # redirect to a suffixed target for the actual library. + if (_main_target_suffix != "") { + group(_target_name) { + testonly = _testonly + if (defined(_visibility)) { + visibility = _visibility + } + public_deps = [ ":${_target_name}${_main_target_suffix}" ] + public_deps += _cxx_generated_deps_for_cpp + } + } + _rustc_metadata = "" if (defined(invoker.rustc_metadata)) { _rustc_metadata = invoker.rustc_metadata } - group(_target_name) { - testonly = _testonly - if (defined(_visibility)) { - visibility = _visibility - } - - # Both the C++ bindings (if present) and the Rust crate should be treated - # like direct dependencies, so we expose them both in public_deps. - public_deps = [ ":${_target_name}${_main_target_suffix}" ] - - # TODO(danakj): This would not be needed if we stopped forwarding through - # a group in the common (non-procmacro) case. - if (_is_data_dep) { - data_deps = [ ":${_target_name}${_main_target_suffix}" ] - } - - if (_cxx_bindings != []) { - public_deps += [ ":${_target_name}_cxx_generated" ] - - # Additionally, C++ bindings generated by Cxx can include C++ types - # that come from the Cxx library, such as `rust::Str`. So any C++ - # target that depends on a rust target directly may need access to Cxx - # as well, which means it must appear in public_deps. - public_deps += [ "//build/rust:cxx_cppdeps" ] - } else if (!defined(invoker.no_std) || !invoker.no_std) { - # If C++ depends on and links in the library, we need to make sure C++ - # links in the Rust stdlib. This is orthogonal to if the library exports - # bindings for C++ to use. - deps = [ "//build/rust/std:stdlib_for_clang" ] - } - } - _rust_deps = _deps _rust_aliased_deps = _aliased_deps _rust_public_deps = _public_deps @@ -286,24 +295,16 @@ template("rust_target") { } } - # The Rust target (and unit tests) need the Cxx crate when using it to - # generate bindings. if (_cxx_bindings != []) { + # The Rust target (and unit tests) need the Cxx crate when using it to + # generate bindings. _rust_deps += [ "//build/rust:cxx_rustdeps" ] - - # C++ targets can depend on the Rust target from the BUILD.gn file to - # access the headers generated from it - _rust_public_deps += [ ":${_target_name}_cxx_generated" ] } if (!defined(invoker.no_std) || !invoker.no_std) { - _rust_deps += [ "//build/rust/std:stdlib_for_rustc" ] + _rust_deps += [ "//build/rust/std" ] } - # You must go through the groups above to get to these targets. - _visibility = [] - _visibility = [ ":${_target_name}" ] - if (_build_unit_tests) { _unit_test_target = "${_target_name}_unittests" if (defined(invoker.unit_test_target)) { @@ -370,15 +371,28 @@ template("rust_target") { "test_inputs", ]) + if (_main_target_suffix != "") { + # There's a group that depends on this target, and dependencies must + # be through that group. + visibility = [ ":$_target_name" ] + not_needed([ "_visibility" ]) + } else if (defined(_visibility)) { + visibility = _visibility + } + testonly = _testonly - visibility = _visibility crate_name = _crate_name crate_root = _crate_root configs = [] configs = _configs - deps = _rust_deps + deps = _rust_deps + _cxx_generated_deps_for_rust aliased_deps = _rust_aliased_deps public_deps = _rust_public_deps + if (_main_target_suffix == "") { + # When these are not provided by a wrapper group target, they are added + # to the Rust target itself. + public_deps += _cxx_generated_deps_for_cpp + } rustflags = _rustflags if (_rustc_metadata != "") { rustflags += [ "-Cmetadata=${_rustc_metadata}" ] @@ -418,7 +432,7 @@ template("rust_target") { if (_cxx_bindings != []) { rust_cxx("${_target_name}_cxx_generated") { testonly = _testonly - visibility = [ ":${_target_name}${_main_target_suffix}" ] + visibility = [ ":${_target_name}" ] if (defined(_visibility)) { visibility += _visibility } diff --git a/naiveproxy/src/build/rust/std/BUILD.gn b/naiveproxy/src/build/rust/std/BUILD.gn index 77f4b8c38d..9c3db1e1bd 100644 --- a/naiveproxy/src/build/rust/std/BUILD.gn +++ b/naiveproxy/src/build/rust/std/BUILD.gn @@ -2,28 +2,18 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file provides the ability for our C++ toolchain to successfully -# link binaries containing arbitrary Rust code. +# This file provides the Rust standard library for GN targets. # -# By "arbitrary Rust code" I mean .rlib archives full of Rust code, which -# is actually a static archive. +# For Rust targets, it either copies a prebuilt stdlib or builds a stdlib, and +# then points rustc to it with `--sysroot`. # -# Those static libraries don't link as-is into a final executable because -# they're designed for downstream processing by further invocations of rustc -# which link into a final binary. That final invocation of rustc knows how -# to do two things: -# * Find the Rust standard library. -# * Remap some generic allocator symbols to the specific allocator symbols -# in use. -# This file takes care of equivalent tasks for our C++ toolchains. -# C++ targets should depend upon either local_stdlib_for_clang or -# prebuilt_stdlib_for_clang to ensure that Rust code can be linked into their -# C++ executables. +# When linking it ensures the libraries (and their C library dependencies) are +# part of the linker line. If Rust drives the linking, this is redundant but if +# Clang drives the linking it is required. # -# This is obviously a bit fragile - rustc might do other magic in future. -# But, linking with a final C++ toolchain is something often needed, and -# https://github.com/rust-lang/rust/issues/64191 aims to make this -# officially possible. +# Part of the standard library provided here is "remap_alloc" which maps +# allocator functions into the shim provided by PartitionAlloc so that Rust and +# C++ use the same allocator backend. import("//build/config/compiler/compiler.gni") import("//build/config/coverage/coverage.gni") @@ -292,17 +282,13 @@ if (toolchain_has_rust) { visibility = [ ":*" ] } - # Builds the stdlib and points the rustc `--sysroot` to them. Used by - # targets for which linking is driven by Rust (bins and dylibs). - group("stdlib_for_rustc") { - all_dependent_configs = [ ":local_stdlib_sysroot" ] - public_deps = [ ":local_stdlib_libs" ] - } - # Builds and links against the Rust stdlib. Used by targets for which # linking is driven by C++. - group("stdlib_for_clang") { - all_dependent_configs = [ ":stdlib_public_dependent_libs" ] + group("std") { + all_dependent_configs = [ + ":stdlib_public_dependent_libs", + ":local_stdlib_sysroot", + ] public_deps = [ ":local_stdlib_libs", ":remap_alloc", @@ -426,15 +412,7 @@ if (toolchain_has_rust) { visibility = [ ":*" ] } - # Use the sysroot generated by :prebuilt_rustc_copy_to_sysroot. - group("stdlib_for_rustc") { - all_dependent_configs = [ ":prebuilt_stdlib_sysroot" ] - deps = [ ":prebuilt_rustc_copy_to_sysroot" ] - } - - # Links the Rust stdlib. Used by targets for which linking is driven by - # C++. - group("stdlib_for_clang") { + group("std") { all_dependent_configs = [ ":prebuilt_stdlib_libs", ":stdlib_public_dependent_libs", diff --git a/naiveproxy/src/build/rust/std/rules/BUILD.gn b/naiveproxy/src/build/rust/std/rules/BUILD.gn index e368997bf4..207812e5d2 100644 --- a/naiveproxy/src/build/rust/std/rules/BUILD.gn +++ b/naiveproxy/src/build/rust/std/rules/BUILD.gn @@ -38,8 +38,8 @@ cargo_crate("addr2line") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "alloc", @@ -87,7 +87,7 @@ cargo_crate("adler") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" + core = ":rustc_std_workspace_core" } features = [ "compiler_builtins", @@ -241,7 +241,7 @@ cargo_crate("cfg_if") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" + core = ":rustc_std_workspace_core" } features = [ "compiler_builtins", @@ -261,174 +261,175 @@ cargo_crate("cfg_if") { } cargo_crate("compiler_builtins") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/aarch64_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/arm_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/add.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/cmp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/conv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/div.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/extend.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/sub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/float/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/addsub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/leading_zeros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/sdiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/asymmetric.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/binary_long.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/delegate.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/norm_shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/specialized_div_rem/trifecta.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/int/udiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/math.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/mem/impls.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/mem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/mem/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/probestack.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/riscv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/aarch64_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/arm_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/add.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/cmp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/conv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/div.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/extend.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/sub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/float/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/addsub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/leading_zeros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/sdiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/asymmetric.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/binary_long.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/delegate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/norm_shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/specialized_div_rem/trifecta.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/int/udiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/math.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/mem/impls.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/mem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/mem/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/probestack.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/riscv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/x86_64.rs", ] inputs = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/acos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/acosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/acosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/acoshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/asin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/asinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/asinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/asinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atan2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atan2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/atanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/cbrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/cbrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ceil.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ceilf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/copysign.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/copysignf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/cosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/coshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/erf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/erff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/exp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/exp10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/exp10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/exp2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/exp2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/expf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/expm1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/expm1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fabs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fabsf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fdim.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fdimf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fenv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/floor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/floorf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmax.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmaxf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fminf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/fmodf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/frexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/frexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/hypot.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/hypotf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ilogb.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ilogbf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/j0.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/j0f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/j1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/j1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/jn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/jnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_expo2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/k_tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ldexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/ldexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/lgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/lgamma_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/lgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/lgammaf_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log1p.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log1pf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/log2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/logf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/modf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/modff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/nextafter.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/nextafterf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/powf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/rem_pio2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/rem_pio2_large.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/rem_pio2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/remainder.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/remainderf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/remquo.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/remquof.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/rint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/rintf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/round.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/roundf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/scalbn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/scalbnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sincos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sincosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sqrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/sqrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/tgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/src/../libm/src/math/truncf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/acos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/acosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/acosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/acoshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/asin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/asinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/asinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/asinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atan2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atan2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/atanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/cbrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/cbrtf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ceil.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ceilf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/copysign.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/copysignf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/cosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/coshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/erf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/erff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/exp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/exp10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/exp10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/exp2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/exp2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/expf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/expm1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/expm1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fabs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fabsf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fdim.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fdimf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fenv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/floor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/floorf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmax.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmaxf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fminf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/fmodf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/frexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/frexpf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/hypot.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/hypotf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ilogb.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ilogbf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/j0.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/j0f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/j1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/j1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/jn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/jnf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_expo2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/k_tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ldexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/ldexpf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/lgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/lgamma_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/lgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/lgammaf_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log1p.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log1pf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/log2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/logf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/modf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/modff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/nextafter.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/nextafterf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/powf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/rem_pio2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/rem_pio2_large.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/rem_pio2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/remainder.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/remainderf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/remquo.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/remquof.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/rint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/rintf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/round.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/roundf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/scalbn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/scalbnf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sincos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sincosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/sqrtf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/tgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/src/../libm/src/math/truncf.rs", ] no_std = true # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.1.103" + cargo_pkg_version = "0.1.108" cargo_pkg_authors = "Jorge Aparicio " cargo_pkg_name = "compiler_builtins" cargo_pkg_description = "Compiler intrinsics used by the Rust compiler. Also available for other targets if necessary!" @@ -444,7 +445,7 @@ cargo_crate("compiler_builtins") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" + core = ":rustc_std_workspace_core" } features = [ "compiler-builtins", @@ -452,8 +453,8 @@ cargo_crate("compiler_builtins") { "rustc-dep-of-std", "weak-intrinsics", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.103/build.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-0.1.108/build.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -527,6 +528,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/internal_macros.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/mir.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/intrinsics/simd.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/io/borrowed_buf.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/io/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/iter/adapters/array_chunks.rs", @@ -612,6 +614,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/int_macros.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/nonzero.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/overflow_panic.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/saturating.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/shells/i128.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/shells/i16.rs", @@ -629,6 +632,7 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/uint_macros.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/num/wrapping.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ops/arith.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ops/async_function.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ops/bit.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ops/control_flow.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/ops/coroutine.rs", @@ -704,13 +708,6 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/alias.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/cast.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/core_simd_docs.md", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements/const_ptr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements/float.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements/int.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements/mut_ptr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements/uint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/elements.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/eq.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/fmt.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/intrinsics.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/iter.rs", @@ -718,16 +715,25 @@ cargo_crate("core") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/lib.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/masks/bitmask.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/masks/full_masks.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/masks/to_bitmask.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/masks.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ops/assign.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ops/deref.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ops/shift_scalar.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ops/unary.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ops.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/ord.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/select.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/cmp/eq.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/cmp/ord.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/cmp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/num/float.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/num/int.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/num/uint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/num.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/prelude.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/simd/ptr.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/swizzle.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/swizzle_dyn.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/core/src/../../portable-simd/crates/core_simd/src/to_bytes.rs", @@ -966,8 +972,8 @@ cargo_crate("getopts") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" - std = ":rustc_std_workspace_std__rlib" + core = ":rustc_std_workspace_core" + std = ":rustc_std_workspace_std" } features = [ "core", @@ -987,51 +993,50 @@ cargo_crate("getopts") { } cargo_crate("gimli") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/arch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/constants.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/endianity.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/leb128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/addr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/aranges.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/endian_reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/endian_slice.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/index.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/lazy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/lists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/loclists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/lookup.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/pubnames.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/pubtypes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/reader.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/rnglists.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/read/value.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/test_util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/abbrev.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/cfi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/dwarf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/endian_vec.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/line.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/loc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/op.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/range.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/unit.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.0/src/write/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/arch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/constants.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/endianity.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/leb128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/addr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/aranges.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/endian_reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/endian_slice.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/index.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/lists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/loclists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/lookup.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/pubnames.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/pubtypes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/reader.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/rnglists.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/read/value.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/test_util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/abbrev.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/cfi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/dwarf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/endian_vec.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/line.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/loc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/op.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/range.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/str.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/unit.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/gimli-0.28.1/src/write/writer.rs", ] inputs = [] no_std = true @@ -1039,7 +1044,7 @@ cargo_crate("gimli") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.28.0" + cargo_pkg_version = "0.28.1" cargo_pkg_name = "gimli" cargo_pkg_description = "A library for reading and writing the DWARF debugging format." @@ -1055,8 +1060,8 @@ cargo_crate("gimli") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "read", @@ -1076,32 +1081,32 @@ cargo_crate("gimli") { } cargo_crate("hashbrown") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/helpers.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/raw.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rayon/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rkyv/hash_map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rkyv/hash_set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/rkyv/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/external_trait_impls/serde.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/bitmask.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/neon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/raw/sse2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/rustc_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/scopeguard.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.2/src/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/helpers.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/raw.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rayon/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/hash_map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/hash_set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/rkyv/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/external_trait_impls/serde.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/bitmask.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/neon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/raw/sse2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/rustc_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/scopeguard.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/hashbrown-0.14.3/src/table.rs", ] inputs = [] no_std = true @@ -1109,7 +1114,7 @@ cargo_crate("hashbrown") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.14.2" + cargo_pkg_version = "0.14.3" cargo_pkg_authors = "Amanieu d'Antras " cargo_pkg_name = "hashbrown" cargo_pkg_description = "A Rust port of Google's SwissTable hash map" @@ -1125,8 +1130,8 @@ cargo_crate("hashbrown") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "alloc", @@ -1149,239 +1154,242 @@ cargo_crate("hashbrown") { } cargo_crate("libc") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fixed_width_ints.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/fuchsia/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/hermit/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/hermit/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/hermit/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/psp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/sgx.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/solid/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/solid/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/solid/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/switch.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/teeos/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/aix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/aix/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/long_array.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/apple/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/dragonfly/errno.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/dragonfly/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/freebsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/mips.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/haiku/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/haiku/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/haiku/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/haiku/native.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/haiku/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/hurd/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/hurd/b32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/hurd/b64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/hurd/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/hurd/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b32/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/android/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/emscripten/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/emscripten/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/emscripten/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/emscripten/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/arch/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/arch/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/arch/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/arch/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/csky/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/m68k/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/mips/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/riscv32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/sparc/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/mips64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/sparc64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/gnu/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/hexagon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/mips/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/riscv32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/x86/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b32/x86/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/aarch64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/mips64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/riscv64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/s390x.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/x86_64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/lfs64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/musl/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/non_exhaustive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/arm/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/arm/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips32/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips64/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mips/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/linux/uclibc/x86_64/other.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/linux_like/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/aarch64/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/arm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/espidf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/horizon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/powerpc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/newlib/vita/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/no_align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/nto/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/nto/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/nto/neutrino.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/nto/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/redox/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/compat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/illumos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/solaris.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/unix/solarish/x86_common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/powerpc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/powerpc64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/vxworks/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/wasi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/windows/gnu/align.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/windows/gnu/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/windows/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/windows/msvc/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/src/xous.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fixed_width_ints.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/fuchsia/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/hermit/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/psp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/sgx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/solid/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/switch.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/teeos/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/aix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/aix/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/long_array.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/apple/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/dragonfly/errno.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/dragonfly/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd11/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd11/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd12/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd13/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd14/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/freebsd15/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/freebsd/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/freebsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/mips.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/netbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/riscv64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/sparc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/bsd/netbsdlike/openbsd/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/native.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/haiku/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/b32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/b64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/hurd/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/android/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/emscripten/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/arch/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/csky/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/csky/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/m68k/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/m68k/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mips/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/riscv32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/sparc/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/sparc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/fallback.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/ilp32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/lp64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/loongarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/loongarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mips64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/powerpc64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/powerpc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/sparc64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/sparc64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/not_x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/b64/x86_64/x32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/gnu/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mips/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/riscv32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/riscv32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/x86/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b32/x86/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/int128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/mips64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/riscv64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/riscv64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/s390x.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/x86_64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/b64/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/lfs64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/musl/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/non_exhaustive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/arm/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips32/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mips64/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mips/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/l4re.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/linux/uclibc/x86_64/other.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/linux_like/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/aarch64/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/arm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/espidf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/horizon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/powerpc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/newlib/vita/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/no_align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/neutrino.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/nto/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/redox/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/compat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/illumos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/solaris.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/unix/solarish/x86_common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/powerpc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/powerpc64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/vxworks/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/wasi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/gnu/align.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/gnu/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/windows/msvc/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/src/xous.rs", ] inputs = [] no_std = true @@ -1389,7 +1397,7 @@ cargo_crate("libc") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2015" - cargo_pkg_version = "0.2.150" + cargo_pkg_version = "0.2.153" cargo_pkg_authors = "The Rust Project Developers" cargo_pkg_name = "libc" cargo_pkg_description = "Raw FFI bindings to platform libraries like libc." @@ -1409,8 +1417,8 @@ cargo_crate("libc") { "rustc-dep-of-std", "rustc-std-workspace-core", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.150/build.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/libc-0.2.153/build.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -1485,7 +1493,7 @@ cargo_crate("memchr") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" + core = ":rustc_std_workspace_core" } features = [ "compiler_builtins", @@ -1507,18 +1515,18 @@ cargo_crate("memchr") { } cargo_crate("miniz_oxide") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/deflate/buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/deflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/deflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/deflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/inflate/core.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/inflate/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/inflate/output_buffer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/inflate/stream.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.1/src/shared.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/deflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/core.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/output_buffer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/inflate/stream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/miniz_oxide-0.7.2/src/shared.rs", ] inputs = [] no_std = true @@ -1526,7 +1534,7 @@ cargo_crate("miniz_oxide") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.7.1" + cargo_pkg_version = "0.7.2" cargo_pkg_authors = "Frommi , oyvindln " cargo_pkg_name = "miniz_oxide" cargo_pkg_description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" @@ -1543,8 +1551,8 @@ cargo_crate("miniz_oxide") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "alloc", @@ -1565,80 +1573,82 @@ cargo_crate("miniz_oxide") { } cargo_crate("object") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/elf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/endian.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/pod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/any.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/archive.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/coff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/attributes.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/compression.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/dynamic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/hash.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/note.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/elf/version.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/dyld_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/fat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/load_command.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/macho/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/data_directory.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/export.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/import.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/resource.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/rich.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/pe/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/read_cache.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/read_ref.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/wasm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/comdat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/file.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/relocation.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/section.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/segment.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/read/xcoff/symbol.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/coff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/elf/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/elf/object.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/elf/writer.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/macho.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/pe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/string.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/util.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/write/xcoff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.1/src/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/elf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/endian.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/pod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/any.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/archive.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/coff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/attributes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/compression.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/dynamic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/hash.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/note.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/elf/version.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/dyld_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/fat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/load_command.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/macho/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/data_directory.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/export.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/import.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/resource.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/rich.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/pe/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/read_cache.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/read_ref.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/wasm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/comdat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/file.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/relocation.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/section.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/segment.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/read/xcoff/symbol.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/coff/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/object.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/elf/writer.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/macho.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/pe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/string.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/write/xcoff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/object-0.32.2/src/xcoff.rs", ] inputs = [] no_std = true @@ -1646,7 +1656,7 @@ cargo_crate("object") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "0.32.1" + cargo_pkg_version = "0.32.2" cargo_pkg_name = "object" cargo_pkg_description = "A unified interface for reading and writing object file formats." @@ -1663,8 +1673,8 @@ cargo_crate("object") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "alloc", @@ -1678,6 +1688,7 @@ cargo_crate("object") { "read_core", "rustc-dep-of-std", "unaligned", + "xcoff", ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", @@ -1696,6 +1707,7 @@ cargo_crate("panic_abort") { sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/panic_abort/src/android.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/panic_abort/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/panic_abort/src/zkvm.rs", ] inputs = [] no_std = true @@ -1889,7 +1901,7 @@ cargo_crate("rustc_demangle") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" + core = ":rustc_std_workspace_core" } features = [ "compiler_builtins", @@ -2078,7 +2090,6 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/net/udp.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/net/udp/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/benches.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/num/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/aix/fs.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/aix/mod.rs", @@ -2221,7 +2232,9 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/ffi/definitions/memoryflags.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services/dns.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services/log.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services/net.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services/systime.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/os/xous/services/ticktimer.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/panic.rs", @@ -2265,250 +2278,278 @@ cargo_crate("std") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sync/remutex/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sync/rwlock.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sync/rwlock/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/small_c_string.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/thread_local/fast_local.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/thread_local/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/thread_local/os_local.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/common/thread_local/static_local.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/fd.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/futex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/thread_local_dtor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/hermit/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/abi.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/error.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/spin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/task.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/thread_parking.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/itron/time/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/cmath.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/os_str/bytes.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/os_str/bytes/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/os_str/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/os_str/wtf8.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/small_c_string.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/thread_local/fast_local.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/thread_local/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/thread_local/os_local.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/common/thread_local/static_local.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/fd.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/futex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/hermit/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/abi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/error.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/spin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/task.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/thread_parking.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/itron/time/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/mem.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/panic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/reloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/tls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/tls/sync_bitset.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/tls/sync_bitset/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/raw.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/abi/usercalls/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/fd.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/rwlock/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/thread_parking.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/spin_mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/spin_mutex/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/unsafe_list.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/sgx/waitqueue/unsafe_list/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/abi/sockets.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/error.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/io.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/solid/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/locks/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/locks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/locks/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/rand.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/teeos/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/helpers.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/uefi/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/android.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fd.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fd/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/futex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/io.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/kernel_copy.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/kernel_copy/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/l4re.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/fuchsia_mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/futex_condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/futex_mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/futex_rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/pthread_condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/pthread_mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/locks/queue_rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/os/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/pipe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_common/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_fuchsia.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_unix.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_unix/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_unsupported.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_unsupported/wait_status.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_unsupported/wait_status/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/process_vxworks.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/process/zircon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/rand.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/stack_overflow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_parking/darwin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_parking/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_parking/netbsd.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/thread_parking/pthread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unix/weak.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/common.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/io.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/locks/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/locks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/locks/mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/locks/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/once.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/pipe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/process.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/thread_parking.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/unsupported/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/fd.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/io.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasi/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/atomics/futex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/atomics/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/wasm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/alloc/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/api.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/args/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/c.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/c/windows_sys.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/compat.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/fs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/handle.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/handle/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/io.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/locks/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/locks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/locks/mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/locks/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/memchr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/net.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/os/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/pipe.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/process.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/process/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/rand.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/stack_overflow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/stack_overflow_uwp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/stdio/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread_local_dtor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread_local_key/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/thread_parking.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/windows/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/locks/condvar.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/locks/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/locks/mutex.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/locks/rwlock.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/net/dns.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/net/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/net/tcplistener.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/net/tcpstream.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/net/udp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/thread.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/thread_parking.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/xous/time.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/abi.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/args.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/os.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/stdio.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/pal/zkvm/thread_local_key.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/sgx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/unix.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/unsupported_backslash.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/windows.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/path/windows/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/eh.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/dwarf/tests.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/emcc.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/gcc.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/personality/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/mem.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/panic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/reloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/tls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/tls/sync_bitset.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/tls/sync_bitset/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/usercalls/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/usercalls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/usercalls/raw.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/abi/usercalls/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/fd.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/path.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/rwlock/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/thread_parking.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/spin_mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/spin_mutex/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/unsafe_list.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/sgx/waitqueue/unsafe_list/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/abi/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/abi/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/abi/sockets.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/error.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/io.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/path.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/thread_local_dtor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/solid/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/helpers.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/path.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/uefi/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/android.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/cmath.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/fd.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/fd/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/futex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/io.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/kernel_copy.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/kernel_copy/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/l4re.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/fuchsia_mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/futex_condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/futex_mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/futex_rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/pthread_condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/pthread_mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/locks/pthread_rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/os/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/os_str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/os_str/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/path.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/pipe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_common/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_fuchsia.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_unix.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_unix/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_unsupported.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_unsupported/wait_status.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_unsupported/wait_status/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/process_vxworks.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/process/zircon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/rand.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/stack_overflow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_local_dtor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_parking/darwin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_parking/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_parking/netbsd.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/thread_parking/pthread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unix/weak.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/common.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/io.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/locks/condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/locks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/locks/mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/locks/rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/once.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/pipe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/process.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/thread_local_dtor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/thread_parking.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/unsupported/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/fd.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/io.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasi/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasm/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasm/atomics/futex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasm/atomics/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasm/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/wasm/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/alloc/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/api.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/args.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/args/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/c.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/c/windows_sys.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/cmath.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/compat.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/fs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/handle.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/handle/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/io.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/locks/condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/locks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/locks/mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/locks/rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/memchr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/net.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/os/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/os_str.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/path.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/path/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/pipe.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/process.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/process/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/rand.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/stack_overflow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/stack_overflow_uwp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/stdio/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/thread_local_dtor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/thread_local_key/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/thread_parking.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/windows/time.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/locks/condvar.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/locks/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/locks/mutex.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/locks/rwlock.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/os.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/stdio.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/thread.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/thread_local_key.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys/xous/time.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/backtrace.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/fs.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/std/src/sys_common/io.rs", @@ -2669,6 +2710,7 @@ cargo_crate("std_detect") { sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/aarch64.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/loongarch.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/mips.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/mips64.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/arch/mod.rs", @@ -2690,6 +2732,7 @@ cargo_crate("std_detect") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/mips.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/powerpc.rs", @@ -2725,8 +2768,8 @@ cargo_crate("std_detect") { "//build/rust/std:std_build_deps", ] aliased_deps = { - alloc = ":rustc_std_workspace_alloc__rlib" - core = ":rustc_std_workspace_core__rlib" + alloc = ":rustc_std_workspace_alloc" + core = ":rustc_std_workspace_core" } features = [ "alloc", @@ -2762,7 +2805,6 @@ cargo_crate("test") { "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/formatters/pretty.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/formatters/terse.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/helpers/concurrency.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/helpers/exit_code.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/helpers/metrics.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/helpers/mod.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/test/src/helpers/shuffle.rs", @@ -2799,6 +2841,7 @@ cargo_crate("test") { deps = [ ":core", ":getopts", + ":libc", ":panic_abort", ":panic_unwind", ":std", @@ -2818,11 +2861,11 @@ cargo_crate("test") { } cargo_crate("unicode_width") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.10/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.10/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.10/src/tables.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.10/src/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/tables.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/vendor/unicode-width-0.1.11/src/tests.rs", ] inputs = [] no_std = true @@ -2830,7 +2873,7 @@ cargo_crate("unicode_width") { # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2015" - cargo_pkg_version = "0.1.10" + cargo_pkg_version = "0.1.11" cargo_pkg_authors = "kwantam , Manish Goregaokar " cargo_pkg_name = "unicode-width" @@ -2847,8 +2890,8 @@ cargo_crate("unicode_width") { "//build/rust/std:std_build_deps", ] aliased_deps = { - core = ":rustc_std_workspace_core__rlib" - std = ":rustc_std_workspace_std__rlib" + core = ":rustc_std_workspace_core" + std = ":rustc_std_workspace_std" } features = [ "compiler_builtins", @@ -2873,6 +2916,7 @@ cargo_crate("unwind") { sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/unwind/src/lib.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/unwind/src/libunwind.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/unwind/src/unwinding.rs", ] inputs = [] no_std = true diff --git a/naiveproxy/src/build/rust/tests/test_aliased_deps/BUILD.gn b/naiveproxy/src/build/rust/tests/test_aliased_deps/BUILD.gn index 9576b5885e..98deeb01f5 100644 --- a/naiveproxy/src/build/rust/tests/test_aliased_deps/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/test_aliased_deps/BUILD.gn @@ -17,9 +17,7 @@ rust_static_library("test_aliased_deps") { sources = [ crate_root ] deps = [ ":real_name" ] aliased_deps = { - # Unfortunately we have to know the `__rlib` suffix which is attached to the - # actual rlib in `rust_static_library()`. - other_name = ":real_name__rlib" + other_name = ":real_name" } build_native_rust_unit_tests = true } diff --git a/naiveproxy/src/build/rust/tests/test_control_flow_guard/BUILD.gn b/naiveproxy/src/build/rust/tests/test_control_flow_guard/BUILD.gn index 202c5b0f0f..33401219fd 100644 --- a/naiveproxy/src/build/rust/tests/test_control_flow_guard/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/test_control_flow_guard/BUILD.gn @@ -8,7 +8,4 @@ rust_executable("test_control_flow_guard") { allow_unsafe = true crate_root = "test_control_flow_guard.rs" sources = [ crate_root ] - - # Used as a data dep by base_unittests. - is_data_dep = true } diff --git a/naiveproxy/src/build/rust/tests/test_simple_rust_exe/BUILD.gn b/naiveproxy/src/build/rust/tests/test_simple_rust_exe/BUILD.gn index 9f6ee20f2b..9d4dcf71e1 100644 --- a/naiveproxy/src/build/rust/tests/test_simple_rust_exe/BUILD.gn +++ b/naiveproxy/src/build/rust/tests/test_simple_rust_exe/BUILD.gn @@ -9,5 +9,5 @@ executable("test_simple_rust_exe") { crate_root = "main.rs" sources = [ crate_root ] - deps = [ "//build/rust/std:stdlib_for_rustc" ] + deps = [ "//build/rust/std" ] } diff --git a/naiveproxy/src/build/sanitizers/tsan_suppressions.cc b/naiveproxy/src/build/sanitizers/tsan_suppressions.cc index d90546efca..2f3b3826b2 100644 --- a/naiveproxy/src/build/sanitizers/tsan_suppressions.cc +++ b/naiveproxy/src/build/sanitizers/tsan_suppressions.cc @@ -16,7 +16,8 @@ // for the instructions on writing suppressions. char kTSanDefaultSuppressions[] = // False positives in libdbus.so, libdconfsettings.so, libflashplayer.so, - // libgio.so, libglib.so, libgobject.so, and libfontconfig.so.1. + // libgio.so, libglib.so, libgobject.so, libfontconfig.so.1 and + // swrast_dri.so. // Since we don't instrument them, we cannot reason about the // synchronization in them. "race:libdbus*.so\n" @@ -26,6 +27,7 @@ char kTSanDefaultSuppressions[] = "race:libglib*.so\n" "race:libgobject*.so\n" "race:libfontconfig.so.1\n" + "race:swrast_dri.so\n" // Intentional race in ToolsSanityTest.DataRace in base_unittests. "race:base/tools_sanity_unittest.cc\n" @@ -90,6 +92,11 @@ char kTSanDefaultSuppressions[] = // single global mutex. "deadlock:GlobalSafepoint::EnterGlobalSafepointScope\n" + // Logging crash keys is inherently unsafe. We suppress this rather than fix + // it because OutputCrashKeysToStream is only enabled in non-official builds + // and the race is therefore not present in released builds. + "race:crash_reporter::*::OutputCrashKeysToStream\n" + // End of suppressions. ; // Please keep this semicolon. diff --git a/naiveproxy/src/build/toolchain/concurrent_links.gni b/naiveproxy/src/build/toolchain/concurrent_links.gni index c3275b42fa..c8649d7661 100644 --- a/naiveproxy/src/build/toolchain/concurrent_links.gni +++ b/naiveproxy/src/build/toolchain/concurrent_links.gni @@ -35,6 +35,9 @@ if (concurrent_links == -1) { # Based on measurements of linking chrome.dll and chrome_child.dll, plus # a little padding to account for future growth. _args += [ "--mem_per_link_gb=45" ] + } else if (is_android) { + # Large solink of Android official builds take 30-60GB. + _args += [ "--mem_per_link_gb=30" ] } else { _args += [ "--mem_per_link_gb=20" ] } diff --git a/naiveproxy/src/build/toolchain/gcc_toolchain.gni b/naiveproxy/src/build/toolchain/gcc_toolchain.gni index 54db5f9938..94592ecb5b 100644 --- a/naiveproxy/src/build/toolchain/gcc_toolchain.gni +++ b/naiveproxy/src/build/toolchain/gcc_toolchain.gni @@ -7,6 +7,7 @@ import("//build/config/compiler/compiler.gni") import("//build/config/coverage/coverage.gni") import("//build/config/rust.gni") import("//build/config/sanitizers/sanitizers.gni") +import("//build/config/sysroot.gni") import("//build/config/v8_target_cpu.gni") import("//build/toolchain/cc_wrapper.gni") import("//build/toolchain/goma.gni") @@ -30,8 +31,11 @@ declare_args() { (target_os == "android" || target_os == "win") # Use -MD instead of -MMD for compiler commands. This is useful for tracking - # the comprehensive set of dependencies. - system_headers_in_deps = false + # the comprehensive set of dependencies. It's also required when building + # without the sysroot so that updates to system header files trigger a + # rebuild (when using the sysroot, the CR_SYSROOT_KEY define takes care of + # this already). + system_headers_in_deps = !use_sysroot } # When the arg is set via args.gn, it applies to all toolchains. In order to not diff --git a/naiveproxy/src/build/toolchain/toolchain.gni b/naiveproxy/src/build/toolchain/toolchain.gni index 23ec903ad8..14aa5f76d3 100644 --- a/naiveproxy/src/build/toolchain/toolchain.gni +++ b/naiveproxy/src/build/toolchain/toolchain.gni @@ -47,17 +47,13 @@ declare_args() { if (llvm_android_mainline) { # https://crbug.com/1481060 clang_version = "17" } else { - clang_version = "18" + clang_version = "19" } } # Extension for shared library files (including leading dot). if (is_apple) { shlib_extension = ".dylib" -} else if (is_android && is_component_build) { - # By appending .cr, we prevent name collisions with libraries already - # loaded by the Android zygote. - shlib_extension = ".cr.so" } else if (is_posix || is_fuchsia) { shlib_extension = ".so" } else if (is_win) { diff --git a/naiveproxy/src/build/util/LASTCHANGE b/naiveproxy/src/build/util/LASTCHANGE index 260f173fc8..78c2e3a687 100644 --- a/naiveproxy/src/build/util/LASTCHANGE +++ b/naiveproxy/src/build/util/LASTCHANGE @@ -1,2 +1,2 @@ -LASTCHANGE=1570c0819d0acc84beabfb6e050f269a464231d5-refs/branch-heads/6261@{#745} +LASTCHANGE=da5d1859418105ffdce20eac46d7e044eb9bc55e-refs/branch-heads/6312@{#551} LASTCHANGE_YEAR=2024 diff --git a/naiveproxy/src/build/util/LASTCHANGE.committime b/naiveproxy/src/build/util/LASTCHANGE.committime index 2145d46f89..923ab26381 100644 --- a/naiveproxy/src/build/util/LASTCHANGE.committime +++ b/naiveproxy/src/build/util/LASTCHANGE.committime @@ -1 +1 @@ -1707859473 \ No newline at end of file +1710266966 \ No newline at end of file diff --git a/naiveproxy/src/build/util/ide_query b/naiveproxy/src/build/util/ide_query new file mode 100755 index 0000000000..80536c1cc0 --- /dev/null +++ b/naiveproxy/src/build/util/ide_query @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +# Copyright 2024 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. +"""A script gets the information needed by lDE language services. + +Expected to run it at repository root, where top DEP, .gn etc exists. +Not intended to run by user. +See go/reqs-for-peep +""" + +import argparse +import os +import re +import subprocess +import sys + +def _gn_lines(output_dir, path): + """ + Generator function that returns args.gn lines one at a time, following + import directives as needed. + """ + import_re = re.compile(r'\s*import\("(.*)"\)') + with open(path, encoding="utf-8") as f: + for line in f: + match = import_re.match(line) + if match: + raw_import_path = match.groups()[0] + if raw_import_path[:2] == "//": + import_path = os.path.normpath( + os.path.join(output_dir, "..", "..", + raw_import_path[2:])) + else: + import_path = os.path.normpath( + os.path.join(os.path.dirname(path), raw_import_path)) + for import_line in _gn_lines(output_dir, import_path): + yield import_line + else: + yield line + +def _use_reclient(outdir): + args_gn = os.path.join(outdir, 'args.gn') + if not os.path.exists(args_gn): + return False + for line in _gn_lines(outdir, args_gn): + line_without_comment = line.split('#')[0] + if re.search(r"(^|\s)(use_remoteexec)\s*=\s*true($|\s)", + line_without_comment): + return True + return False + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--source', action='append', + help=('The source file being analyzed.' + 'Multiple --source arguments can be passed in order to batch ' + 'process is desired. ')) + parser.add_argument('--perform-build', action='store_true', + help=('If specified, actually build the target, including any generated ' + 'prerequisite files. ' + 'If --perform-build is not passed, the contents of ' + 'the GeneratedFile results will only be returned if a build has ' + 'been previously completed, and may be stale.')) + parser.add_argument('--out-dir', + help=('Output directory, containing args.gn, which specifies the build ' + 'configuration.')) + options = parser.parse_args() + + this_dir = os.path.dirname(__file__) + repo_root = os.path.join(this_dir, '..', '..') + + targets = [] + for source in options.source: + # source is repo root (cwd) relative, + # but siso uses out dir relative target. + target = os.path.relpath(source, start=options.out_dir) + "^" + targets.append(target) + + if options.perform_build: + if _use_reclient(options.out_dir): + args = ['autoninja', '-C', options.out_dir] + else: + args = ['siso', 'ninja', '-C', options.out_dir] + args.extend(targets) + p = subprocess.run(args, cwd=repo_root, capture_output=True) + if p.returncode != 0: + # TODO: report error in IdeAnalysis.Status? + sys.stderr.write('build failed with %d\n%s\n%s' % ( + p.returncode, p.stdout, p.stderr)) + return 1 + + args = ['siso', 'query', 'ideanalysis', '-C', options.out_dir] + args.extend(targets) + subprocess.run(args, cwd=repo_root, check=True) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/naiveproxy/src/build/whitespace_file.txt b/naiveproxy/src/build/whitespace_file.txt index f66509b02b..30daae2769 100644 --- a/naiveproxy/src/build/whitespace_file.txt +++ b/naiveproxy/src/build/whitespace_file.txt @@ -208,4 +208,4 @@ STEP 4: When hot, cook your pancakes for 1 min on each side until golden, keepin in a low oven as you go. STEP 5: Serve with lemon wedges and caster sugar, or your favourite filling. Once cold, you can layer the pancakes between baking parchment, -then wrap in cling film and freeze for up to 2 months. +then wrap in cling film and freeze for up to 2 months. diff --git a/naiveproxy/src/build_overrides/build.gni b/naiveproxy/src/build_overrides/build.gni index 10907859ff..3443a990d2 100644 --- a/naiveproxy/src/build_overrides/build.gni +++ b/naiveproxy/src/build_overrides/build.gni @@ -14,6 +14,10 @@ import("//build/config/gclient_args.gni") # Some non-Chromium builds don't support building java targets. enable_java_templates = false +# Variable that can be used to support multiple build scenarios, like when +# V8 is embedded within a target. +build_with_v8_embedder = build_with_chromium + # Enables assertions on safety checks in libc++. # # This should be set to true whenever building with Chrome's custom libc++ in @@ -40,7 +44,7 @@ declare_args() { # TODO(crbug/1006541): Switch to perfetto's client library on all platforms. use_perfetto_client_library = (is_linux || is_android || (use_blink && is_ios) || is_win || - is_chromeos) && !is_castos + is_chromeos || is_mac) && !is_castos # Limits the defined //third_party/android_deps targets to only "buildCompile" # and "buildCompileNoDeps" targets. This is useful for third-party diff --git a/naiveproxy/src/build_overrides/partition_alloc.gni b/naiveproxy/src/build_overrides/partition_alloc.gni index 922ccfa183..65f036262a 100644 --- a/naiveproxy/src/build_overrides/partition_alloc.gni +++ b/naiveproxy/src/build_overrides/partition_alloc.gni @@ -71,7 +71,7 @@ if (_default_use_allocator_shim && _is_partition_alloc_everywhere_platform && use_partition_alloc_as_malloc_default = _default_allocator == "partition" use_allocator_shim_default = _default_use_allocator_shim -_is_brp_supported = (is_win || is_android || is_linux || is_mac || +_is_brp_supported = (is_win || is_android || is_linux || is_mac || is_ios || is_chromeos) && use_partition_alloc_as_malloc_default enable_backup_ref_ptr_support_default = _is_brp_supported diff --git a/naiveproxy/src/buildtools/deps_revisions.gni b/naiveproxy/src/buildtools/deps_revisions.gni index cca852678d..ddcc2f1372 100644 --- a/naiveproxy/src/buildtools/deps_revisions.gni +++ b/naiveproxy/src/buildtools/deps_revisions.gni @@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "28aa23ffb4c7344914a5b4ac7169f12e5a12333f" + libcxx_revision = "834e97d73f13a166af65952fb681071eec87a2c4" } diff --git a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn index bd74fca23e..5060bf19f9 100644 --- a/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn +++ b/naiveproxy/src/buildtools/third_party/libc++/BUILD.gn @@ -192,7 +192,7 @@ target(_libcxx_target_type, "libc++") { # specified in the C++ spec 3.7.4p2, which makes them always have default # visibility. This option is needed to force hidden visibility since # -fvisibility=hidden doesn't have the desired effect. - cflags = [ "-fvisibility-global-new-delete-hidden" ] + cflags = [ "-fvisibility-global-new-delete=force-hidden" ] } else { defines += [ # This resets the visibility to default only for the various diff --git a/naiveproxy/src/chrome/VERSION b/naiveproxy/src/chrome/VERSION index c4a60a3cff..f75ace5a0a 100644 --- a/naiveproxy/src/chrome/VERSION +++ b/naiveproxy/src/chrome/VERSION @@ -1,4 +1,4 @@ -MAJOR=122 +MAJOR=123 MINOR=0 -BUILD=6261 -PATCH=43 +BUILD=6312 +PATCH=40 diff --git a/naiveproxy/src/chrome/build/android-arm32.pgo.txt b/naiveproxy/src/chrome/build/android-arm32.pgo.txt index d479b39ae8..d5e2cc8248 100644 --- a/naiveproxy/src/chrome/build/android-arm32.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm32.pgo.txt @@ -1 +1 @@ -chrome-android32-main-1705946049-1107c5d5377f3a310e11342b86b346e89ede0a92.profdata +chrome-android32-main-1708386286-0ef8320101516a6589554975261b1f9c17c15556-72ffdabd5430413eb5beb657f1c3f32221c4c014.profdata diff --git a/naiveproxy/src/chrome/build/android-arm64.pgo.txt b/naiveproxy/src/chrome/build/android-arm64.pgo.txt index 30eaf20e2f..02cd24d1a8 100644 --- a/naiveproxy/src/chrome/build/android-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/android-arm64.pgo.txt @@ -1 +1 @@ -chrome-android64-main-1705859715-29c601224c79dbb822758f85d5c3bb8e08f60dcc.profdata +chrome-android64-main-1708386286-149336b0094939c79303a748b0223213e84f59a1-72ffdabd5430413eb5beb657f1c3f32221c4c014.profdata diff --git a/naiveproxy/src/chrome/build/lacros-arm.pgo.txt b/naiveproxy/src/chrome/build/lacros-arm.pgo.txt deleted file mode 100644 index 19d46edbec..0000000000 --- a/naiveproxy/src/chrome/build/lacros-arm.pgo.txt +++ /dev/null @@ -1 +0,0 @@ -chrome-chromeos-arm-generic-main-1691064300-90f42dbcd7b06eea1e2e1859a8111fc05d50b4b1.profdata diff --git a/naiveproxy/src/chrome/build/lacros-arm64.pgo.txt b/naiveproxy/src/chrome/build/lacros-arm64.pgo.txt index 01ce3e01a7..cd986b38f4 100644 --- a/naiveproxy/src/chrome/build/lacros-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/lacros-arm64.pgo.txt @@ -1 +1 @@ -chrome-chromeos-arm64-generic-main-1705924404-61aa373b87e4ef10bce1d9838ac74b8d450d3061.profdata +chrome-chromeos-arm64-generic-main-1706745912-3ca605590087d3dced768f774a6f119b842ae228.profdata diff --git a/naiveproxy/src/chrome/build/lacros64.pgo.txt b/naiveproxy/src/chrome/build/lacros64.pgo.txt index 1ec485d747..1ade05f24a 100644 --- a/naiveproxy/src/chrome/build/lacros64.pgo.txt +++ b/naiveproxy/src/chrome/build/lacros64.pgo.txt @@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1700135535-ab414456fe7c82d1ac5176320d01171f45df2e14.profdata +chrome-chromeos-amd64-generic-main-1708386286-30aa90395412d5c677007141c71d85c606aced0d-72ffdabd5430413eb5beb657f1c3f32221c4c014.profdata diff --git a/naiveproxy/src/chrome/build/linux.pgo.txt b/naiveproxy/src/chrome/build/linux.pgo.txt index d1ee72e99c..482bbfbc90 100644 --- a/naiveproxy/src/chrome/build/linux.pgo.txt +++ b/naiveproxy/src/chrome/build/linux.pgo.txt @@ -1 +1 @@ -chrome-linux-6261-1707846690-1391fcc4772c0b31e214f533af5cafa87e4ccf40.profdata +chrome-linux-6312-1710232336-55ec5e20adb987a833d822fa3c03ffde72e6a2bb-33fd71f0cc028eebdc456b115c2cc23a6c31514b.profdata diff --git a/naiveproxy/src/chrome/build/mac-arm.pgo.txt b/naiveproxy/src/chrome/build/mac-arm.pgo.txt index 14b80f4470..88815c3775 100644 --- a/naiveproxy/src/chrome/build/mac-arm.pgo.txt +++ b/naiveproxy/src/chrome/build/mac-arm.pgo.txt @@ -1 +1 @@ -chrome-mac-arm-main-1705960735-a4edd2bc1d969d8b2e8d77be31058ed300239d2f.profdata +chrome-mac-arm-main-1708386286-01b1065f25738a70717c12ea78d8c6d981061f8f-72ffdabd5430413eb5beb657f1c3f32221c4c014.profdata diff --git a/naiveproxy/src/chrome/build/mac.pgo.txt b/naiveproxy/src/chrome/build/mac.pgo.txt index b26abb0e1d..cc9a50680b 100644 --- a/naiveproxy/src/chrome/build/mac.pgo.txt +++ b/naiveproxy/src/chrome/build/mac.pgo.txt @@ -1 +1 @@ -chrome-mac-6261-1707815702-0a02cc11c74c2c740a14df152e8c83d1e57e17b4.profdata +chrome-mac-main-1706096829-9b2160cb39f31cc28c32402938f110df1a69fea2.profdata diff --git a/naiveproxy/src/chrome/build/win-arm64.pgo.txt b/naiveproxy/src/chrome/build/win-arm64.pgo.txt index 2bcdebe6fa..4fbf7657e3 100644 --- a/naiveproxy/src/chrome/build/win-arm64.pgo.txt +++ b/naiveproxy/src/chrome/build/win-arm64.pgo.txt @@ -1 +1 @@ -chrome-win-arm64-main-1705946049-3bf8bd91a0fc0f118ee74cd78ea72620cb3b3820.profdata +chrome-win-arm64-main-1708322053-df56b306a957f0257e2903c443bece58cc5fcf0b-fbc30e15b0d2590e506762a5dab342a272788c5c.profdata diff --git a/naiveproxy/src/chrome/build/win64.pgo.txt b/naiveproxy/src/chrome/build/win64.pgo.txt index 57969ea40c..9d7ba2a6d7 100644 --- a/naiveproxy/src/chrome/build/win64.pgo.txt +++ b/naiveproxy/src/chrome/build/win64.pgo.txt @@ -1 +1 @@ -chrome-win64-6261-1707815702-480edc48d8a530f349b0e8eb09ff413a229c57b4.profdata +chrome-win64-main-1706108392-59536a3715cd7cbbceb8229606f3d05b6a1d5c26.profdata diff --git a/naiveproxy/src/components/version_info/DIR_METADATA b/naiveproxy/src/components/version_info/DIR_METADATA index 14b5edb5d6..45f7798a68 100644 --- a/naiveproxy/src/components/version_info/DIR_METADATA +++ b/naiveproxy/src/components/version_info/DIR_METADATA @@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals" } +buganizer_public: { + component_id: 1456292 +} diff --git a/naiveproxy/src/crypto/BUILD.gn b/naiveproxy/src/crypto/BUILD.gn index a958629d3f..0dad610c4f 100644 --- a/naiveproxy/src/crypto/BUILD.gn +++ b/naiveproxy/src/crypto/BUILD.gn @@ -56,6 +56,8 @@ component("crypto") { "unexportable_key_metrics.cc", "unexportable_key_metrics.h", "unexportable_key_software_unsecure.cc", + "user_verifying_key.cc", + "user_verifying_key.h", ] deps = [ "//base/third_party/dynamic_annotations" ] @@ -67,7 +69,11 @@ component("crypto") { ] if (is_apple) { - sources += [ "apple_keychain.h" ] + sources += [ + "apple_keychain.h", + "apple_keychain_v2.h", + "apple_keychain_v2.mm", + ] if (is_mac) { sources += [ "apple_keychain_mac.cc" ] @@ -92,6 +98,7 @@ component("crypto") { "scoped_capi_types.h", "scoped_cng_types.h", "unexportable_key_win.cc", + "user_verifying_key_win.cc", ] libs = [ "ncrypt.lib" ] } diff --git a/naiveproxy/src/crypto/DIR_METADATA b/naiveproxy/src/crypto/DIR_METADATA index 54e5bb81d8..7120730774 100644 --- a/naiveproxy/src/crypto/DIR_METADATA +++ b/naiveproxy/src/crypto/DIR_METADATA @@ -1,12 +1,7 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { +monorail: { component: "Internals>Network>SSL" } team_email: "trusty-transport@chromium.org" +buganizer_public: { + component_id: 1456816 +} diff --git a/naiveproxy/src/crypto/aead.cc b/naiveproxy/src/crypto/aead.cc index b0845c3075..dfadecfb1d 100644 --- a/naiveproxy/src/crypto/aead.cc +++ b/naiveproxy/src/crypto/aead.cc @@ -8,7 +8,8 @@ #include #include -#include "base/strings/string_util.h" +#include "base/containers/span.h" +#include "base/numerics/checked_math.h" #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/aes.h" #include "third_party/boringssl/src/include/openssl/evp.h" @@ -41,28 +42,23 @@ void Aead::Init(base::span key) { key_ = key; } -static base::span ToSpan(std::string_view sp) { - return base::as_bytes(base::make_span(sp)); -} - void Aead::Init(const std::string* key) { - Init(ToSpan(*key)); + Init(base::as_byte_span(*key)); } std::vector Aead::Seal( base::span plaintext, base::span nonce, base::span additional_data) const { - const size_t max_output_length = - EVP_AEAD_max_overhead(aead_) + plaintext.size(); - CHECK(max_output_length >= plaintext.size()); - std::vector ret; - ret.resize(max_output_length); + size_t max_output_length = + base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_)) + .ValueOrDie(); + std::vector ret(max_output_length); - size_t output_length; - CHECK(Seal(plaintext, nonce, additional_data, ret.data(), &output_length, - max_output_length)); - ret.resize(output_length); + std::optional output_length = + Seal(plaintext, nonce, additional_data, ret); + CHECK(output_length); + ret.resize(*output_length); return ret; } @@ -70,20 +66,21 @@ bool Aead::Seal(std::string_view plaintext, std::string_view nonce, std::string_view additional_data, std::string* ciphertext) const { - const size_t max_output_length = - EVP_AEAD_max_overhead(aead_) + plaintext.size(); - CHECK(max_output_length + 1 >= plaintext.size()); - uint8_t* out_ptr = reinterpret_cast( - base::WriteInto(ciphertext, max_output_length + 1)); + size_t max_output_length = + base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_)) + .ValueOrDie(); + ciphertext->resize(max_output_length); - size_t output_length; - if (!Seal(ToSpan(plaintext), ToSpan(nonce), ToSpan(additional_data), out_ptr, - &output_length, max_output_length)) { + std::optional output_length = + Seal(base::as_byte_span(plaintext), base::as_byte_span(nonce), + base::as_byte_span(additional_data), + base::as_writable_byte_span(*ciphertext)); + if (!output_length) { ciphertext->clear(); return false; } - ciphertext->resize(output_length); + ciphertext->resize(*output_length); return true; } @@ -92,16 +89,15 @@ std::optional> Aead::Open( base::span nonce, base::span additional_data) const { const size_t max_output_length = ciphertext.size(); - std::vector ret; - ret.resize(max_output_length); + std::vector ret(max_output_length); - size_t output_length; - if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length, - max_output_length)) { + std::optional output_length = + Open(ciphertext, nonce, additional_data, ret); + if (!output_length) { return std::nullopt; } - ret.resize(output_length); + ret.resize(*output_length); return ret; } @@ -110,18 +106,18 @@ bool Aead::Open(std::string_view ciphertext, std::string_view additional_data, std::string* plaintext) const { const size_t max_output_length = ciphertext.size(); - CHECK(max_output_length + 1 > max_output_length); - uint8_t* out_ptr = reinterpret_cast( - base::WriteInto(plaintext, max_output_length + 1)); + plaintext->resize(max_output_length); - size_t output_length; - if (!Open(ToSpan(ciphertext), ToSpan(nonce), ToSpan(additional_data), out_ptr, - &output_length, max_output_length)) { + std::optional output_length = + Open(base::as_byte_span(ciphertext), base::as_byte_span(nonce), + base::as_byte_span(additional_data), + base::as_writable_byte_span(*plaintext)); + if (!output_length) { plaintext->clear(); return false; } - plaintext->resize(output_length); + plaintext->resize(*output_length); return true; } @@ -133,50 +129,48 @@ size_t Aead::NonceLength() const { return EVP_AEAD_nonce_length(aead_); } -bool Aead::Seal(base::span plaintext, - base::span nonce, - base::span additional_data, - uint8_t* out, - size_t* output_length, - size_t max_output_length) const { +std::optional Aead::Seal(base::span plaintext, + base::span nonce, + base::span additional_data, + base::span out) const { DCHECK(key_); DCHECK_EQ(NonceLength(), nonce.size()); bssl::ScopedEVP_AEAD_CTX ctx; + size_t out_len; if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) || - !EVP_AEAD_CTX_seal(ctx.get(), out, output_length, max_output_length, + !EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(), nonce.data(), nonce.size(), plaintext.data(), plaintext.size(), additional_data.data(), additional_data.size())) { - return false; + return std::nullopt; } - DCHECK_LE(*output_length, max_output_length); - return true; + DCHECK_LE(out_len, out.size()); + return out_len; } -bool Aead::Open(base::span plaintext, - base::span nonce, - base::span additional_data, - uint8_t* out, - size_t* output_length, - size_t max_output_length) const { +std::optional Aead::Open(base::span plaintext, + base::span nonce, + base::span additional_data, + base::span out) const { DCHECK(key_); DCHECK_EQ(NonceLength(), nonce.size()); bssl::ScopedEVP_AEAD_CTX ctx; + size_t out_len; if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) || - !EVP_AEAD_CTX_open(ctx.get(), out, output_length, max_output_length, + !EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(), nonce.data(), nonce.size(), plaintext.data(), plaintext.size(), additional_data.data(), additional_data.size())) { - return false; + return std::nullopt; } - DCHECK_LE(*output_length, max_output_length); - return true; + DCHECK_LE(out_len, out.size()); + return out_len; } } // namespace crypto diff --git a/naiveproxy/src/crypto/aead.h b/naiveproxy/src/crypto/aead.h index 0bfe472191..4deff590ba 100644 --- a/naiveproxy/src/crypto/aead.h +++ b/naiveproxy/src/crypto/aead.h @@ -71,19 +71,15 @@ class CRYPTO_EXPORT Aead { size_t NonceLength() const; private: - bool Seal(base::span plaintext, - base::span nonce, - base::span additional_data, - uint8_t* out, - size_t* output_length, - size_t max_output_length) const; + std::optional Seal(base::span plaintext, + base::span nonce, + base::span additional_data, + base::span out) const; - bool Open(base::span ciphertext, - base::span nonce, - base::span additional_data, - uint8_t* out, - size_t* output_length, - size_t max_output_length) const; + std::optional Open(base::span ciphertext, + base::span nonce, + base::span additional_data, + base::span out) const; std::optional> key_; raw_ptr aead_; diff --git a/naiveproxy/src/crypto/apple_keychain.h b/naiveproxy/src/crypto/apple_keychain.h index ebb7915d69..e148359453 100644 --- a/naiveproxy/src/crypto/apple_keychain.h +++ b/naiveproxy/src/crypto/apple_keychain.h @@ -8,6 +8,7 @@ #include #include + #include "build/build_config.h" #include "crypto/crypto_export.h" @@ -19,6 +20,7 @@ using AppleSecKeychainItemRef = void*; using AppleSecKeychainItemRef = SecKeychainItemRef; #endif +// DEPRECATED: use `AppleKeychainV2` instead. // Wraps the KeychainServices API in a very thin layer, to allow it to be // mocked out for testing. @@ -27,6 +29,10 @@ using AppleSecKeychainItemRef = SecKeychainItemRef; // SecKeychainFoo). The only exception is Free, which should be used for // anything returned from this class that would normally be freed with // CFRelease (to aid in testing). +// +// The underlying API was deprecated as of the macOS 13 SDK. +// Removal of its use is tracked in https://crbug.com/1348251 +// New code should use AppleKeychainV2. class CRYPTO_EXPORT AppleKeychain { public: AppleKeychain(); diff --git a/naiveproxy/src/crypto/apple_keychain_v2.h b/naiveproxy/src/crypto/apple_keychain_v2.h new file mode 100644 index 0000000000..f9849cd516 --- /dev/null +++ b/naiveproxy/src/crypto/apple_keychain_v2.h @@ -0,0 +1,68 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_APPLE_KEYCHAIN_V2_H_ +#define CRYPTO_APPLE_KEYCHAIN_V2_H_ + +#import +#import +#import + +#include "crypto/crypto_export.h" +#include "base/apple/scoped_cftyperef.h" +#include "base/no_destructor.h" + +namespace crypto { + +// AppleKeychainV2 wraps iOS-style operations from the macOS Security framework +// to work with keys and keychain items. These functions are grouped here so +// they can be mocked out in testing. +class CRYPTO_EXPORT AppleKeychainV2 { + public: + static AppleKeychainV2& GetInstance(); + + AppleKeychainV2(const AppleKeychainV2&) = delete; + AppleKeychainV2& operator=(const AppleKeychainV2&) = delete; + + // KeyCreateRandomKey wraps the |SecKeyCreateRandomKey| function. + virtual base::apple::ScopedCFTypeRef KeyCreateRandomKey( + CFDictionaryRef params, + CFErrorRef* error); + // KeyCreateSignature wraps the |SecKeyCreateSignature| function. + virtual base::apple::ScopedCFTypeRef KeyCreateSignature( + SecKeyRef key, + SecKeyAlgorithm algorithm, + CFDataRef data, + CFErrorRef* error); + // KeyCopyPublicKey wraps the |SecKeyCopyPublicKey| function. + virtual base::apple::ScopedCFTypeRef KeyCopyPublicKey( + SecKeyRef key); + + // ItemCopyMatching wraps the |SecItemCopyMatching| function. + virtual OSStatus ItemCopyMatching(CFDictionaryRef query, CFTypeRef* result); + // ItemDelete wraps the |SecItemDelete| function. + virtual OSStatus ItemDelete(CFDictionaryRef query); + // ItemDelete wraps the |SecItemUpdate| function. + virtual OSStatus ItemUpdate( + CFDictionaryRef query, + base::apple::ScopedCFTypeRef keychain_data); + + protected: + AppleKeychainV2(); + virtual ~AppleKeychainV2(); + + protected: + friend class base::NoDestructor; + friend class ScopedTouchIdTestEnvironment; + + // Set an override to the singleton instance returned by |GetInstance|. The + // caller keeps ownership of the injected keychain and must remove the + // override by calling |ClearInstanceOverride| before deleting it. + static void SetInstanceOverride(AppleKeychainV2* keychain); + static void ClearInstanceOverride(); +}; + +} // namespace crypto + +#endif // CRYPTO_APPLE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/apple_keychain_v2.mm b/naiveproxy/src/crypto/apple_keychain_v2.mm new file mode 100644 index 0000000000..e01cd21ac3 --- /dev/null +++ b/naiveproxy/src/crypto/apple_keychain_v2.mm @@ -0,0 +1,76 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import + +#include "crypto/apple_keychain_v2.h" +#include "base/apple/foundation_util.h" +#include "base/apple/scoped_cftyperef.h" +#include "base/no_destructor.h" + +namespace crypto { + +static AppleKeychainV2* g_keychain_instance_override = nullptr; + +// static +AppleKeychainV2& AppleKeychainV2::GetInstance() { + if (g_keychain_instance_override) { + return *g_keychain_instance_override; + } + static base::NoDestructor k; + return *k; +} + +// static +void AppleKeychainV2::SetInstanceOverride(AppleKeychainV2* AppleKeychainV2) { + CHECK(!g_keychain_instance_override); + g_keychain_instance_override = AppleKeychainV2; +} + +// static +void AppleKeychainV2::ClearInstanceOverride() { + CHECK(g_keychain_instance_override); + g_keychain_instance_override = nullptr; +} + +AppleKeychainV2::AppleKeychainV2() = default; +AppleKeychainV2::~AppleKeychainV2() = default; + +base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCreateRandomKey( + CFDictionaryRef params, + CFErrorRef* error) { + return base::apple::ScopedCFTypeRef( + SecKeyCreateRandomKey(params, error)); +} + +base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCreateSignature( + SecKeyRef key, + SecKeyAlgorithm algorithm, + CFDataRef data, + CFErrorRef* error) { + return base::apple::ScopedCFTypeRef( + SecKeyCreateSignature(key, algorithm, data, error)); +} + +base::apple::ScopedCFTypeRef AppleKeychainV2::KeyCopyPublicKey( + SecKeyRef key) { + return base::apple::ScopedCFTypeRef(SecKeyCopyPublicKey(key)); +} + +OSStatus AppleKeychainV2::ItemCopyMatching( + CFDictionaryRef query, CFTypeRef* result) { + return SecItemCopyMatching(query, result); +} + +OSStatus AppleKeychainV2::ItemDelete(CFDictionaryRef query) { + return SecItemDelete(query); +} + +OSStatus AppleKeychainV2::ItemUpdate( + CFDictionaryRef query, + base::apple::ScopedCFTypeRef keychain_data) { + return SecItemUpdate(query, keychain_data.get()); +} + +} // namespace crypto diff --git a/naiveproxy/src/crypto/fake_apple_keychain_v2.h b/naiveproxy/src/crypto/fake_apple_keychain_v2.h new file mode 100644 index 0000000000..080222c374 --- /dev/null +++ b/naiveproxy/src/crypto/fake_apple_keychain_v2.h @@ -0,0 +1,58 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ +#define CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ + +#include +#include + +#import + +#include "base/apple/scoped_cftyperef.h" +#include "crypto/apple_keychain_v2.h" +#include "crypto/crypto_export.h" + +namespace crypto { + +// FakeAppleKeychainV2 is an implementation of AppleKeychainV2 for testing. It +// works around behavior that can't be relied on in tests, such as writing to +// the actual Keychain or using functionality that requires code-signed, +// entitled builds. +class CRYPTO_EXPORT FakeAppleKeychainV2 : public AppleKeychainV2 { + public: + explicit FakeAppleKeychainV2(const std::string& keychain_access_group); + FakeAppleKeychainV2(const FakeAppleKeychainV2&) = delete; + FakeAppleKeychainV2& operator=(const FakeAppleKeychainV2&) = delete; + ~FakeAppleKeychainV2() override; + + // FakeAppleKeychainV2: + base::apple::ScopedCFTypeRef KeyCreateRandomKey( + CFDictionaryRef params, + CFErrorRef* error) override; + OSStatus ItemCopyMatching(CFDictionaryRef query, CFTypeRef* result) override; + OSStatus ItemDelete(CFDictionaryRef query) override; + OSStatus ItemUpdate(CFDictionaryRef query, + base::apple::ScopedCFTypeRef + keychain_data) override; + + private: + // items_ contains the keychain items created by `KeyCreateRandomKey`. + std::vector> items_; + // keychain_access_group_ is the value of `kSecAttrAccessGroup` that this + // keychain expects to operate on. + base::apple::ScopedCFTypeRef keychain_access_group_; +}; + +// ScopedFakeAppleKeychainV2 installs itself as testing override for +// `AppleKeychainV2::GetInstance()`. +class CRYPTO_EXPORT ScopedFakeAppleKeychainV2 : public FakeAppleKeychainV2 { + public: + explicit ScopedFakeAppleKeychainV2(const std::string& keychain_access_group); + ~ScopedFakeAppleKeychainV2() override; +}; + +} // namespace crypto + +#endif // CRYPTO_FAKE_APPLE_KEYCHAIN_V2_H_ diff --git a/naiveproxy/src/crypto/fake_apple_keychain_v2.mm b/naiveproxy/src/crypto/fake_apple_keychain_v2.mm new file mode 100644 index 0000000000..15a5420f65 --- /dev/null +++ b/naiveproxy/src/crypto/fake_apple_keychain_v2.mm @@ -0,0 +1,234 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/fake_apple_keychain_v2.h" + +#include +#import +#import +#include "base/strings/sys_string_conversions.h" + +#if defined(LEAK_SANITIZER) +#include +#endif + +#include "base/apple/foundation_util.h" +#include "base/apple/scoped_cftyperef.h" +#include "base/check_op.h" +#include "crypto/apple_keychain_v2.h" + +namespace crypto { + +FakeAppleKeychainV2::FakeAppleKeychainV2( + const std::string& keychain_access_group) + : keychain_access_group_( + base::SysUTF8ToCFStringRef(keychain_access_group)) {} +FakeAppleKeychainV2::~FakeAppleKeychainV2() { + // Avoid shutdown leak of error string in Security.framework. + // See https://github.com/apple-oss-distributions/Security/blob/Security-60158.140.3/OSX/libsecurity_keychain/lib/SecBase.cpp#L88 +#if defined(LEAK_SANITIZER) + __lsan_do_leak_check(); +#endif +} + +base::apple::ScopedCFTypeRef FakeAppleKeychainV2::KeyCreateRandomKey( + CFDictionaryRef params, + CFErrorRef* error) { + // Validate certain fields that we always expect to be set. + DCHECK( + base::apple::GetValueFromDictionary(params, kSecAttrLabel)); + DCHECK(base::apple::GetValueFromDictionary( + params, kSecAttrApplicationLabel)); + // kSecAttrApplicationTag is CFDataRef for new credentials and CFStringRef for + // version < 3. Keychain docs say it should be CFDataRef + // (https://developer.apple.com/documentation/security/ksecattrapplicationtag). + DCHECK(base::apple::GetValueFromDictionary( + params, kSecAttrApplicationTag) || + base::apple::GetValueFromDictionary( + params, kSecAttrApplicationTag)); + DCHECK_EQ( + base::apple::GetValueFromDictionary(params, kSecAttrTokenID), + kSecAttrTokenIDSecureEnclave); + DCHECK(CFEqual(base::apple::GetValueFromDictionary( + params, kSecAttrAccessGroup), + keychain_access_group_.get())); + + // Call Keychain services to create a key pair, but first drop all parameters + // that aren't appropriate in tests. + base::apple::ScopedCFTypeRef params_copy( + CFDictionaryCreateMutableCopy(kCFAllocatorDefault, /*capacity=*/0, + params)); + // Don't create a Secure Enclave key. + CFDictionaryRemoveValue(params_copy.get(), kSecAttrTokenID); + // Don't bind to a keychain-access-group, which would require an entitlement. + CFDictionaryRemoveValue(params_copy.get(), kSecAttrAccessGroup); + + base::apple::ScopedCFTypeRef private_key_params( + CFDictionaryCreateMutableCopy( + kCFAllocatorDefault, /*capacity=*/0, + base::apple::GetValueFromDictionary( + params_copy.get(), kSecPrivateKeyAttrs))); + DCHECK(CFEqual(base::apple::GetValueFromDictionary( + private_key_params.get(), kSecAttrIsPermanent), + kCFBooleanTrue)); + CFDictionarySetValue(private_key_params.get(), kSecAttrIsPermanent, + kCFBooleanFalse); + CFDictionaryRemoveValue(private_key_params.get(), kSecAttrAccessControl); + CFDictionaryRemoveValue(private_key_params.get(), + kSecUseAuthenticationContext); + CFDictionarySetValue(params_copy.get(), kSecPrivateKeyAttrs, + private_key_params.get()); + base::apple::ScopedCFTypeRef private_key( + SecKeyCreateRandomKey(params_copy.get(), error)); + if (!private_key) { + return base::apple::ScopedCFTypeRef(); + } + + // Stash everything in `items_` so it can be retrieved in with + // `ItemCopyMatching. This uses the original `params` rather than the modified + // copy so that `ItemCopyMatching()` will correctly filter on + // kSecAttrAccessGroup. + base::apple::ScopedCFTypeRef keychain_item( + CFDictionaryCreateMutableCopy(kCFAllocatorDefault, /*capacity=*/0, + params)); + CFDictionarySetValue(keychain_item.get(), kSecValueRef, private_key.get()); + items_.push_back(keychain_item); + + return private_key; +} + +OSStatus FakeAppleKeychainV2::ItemCopyMatching(CFDictionaryRef query, + CFTypeRef* result) { + // In practice we don't need to care about limit queries, or leaving out the + // SecKeyRef or attributes from the result set. + DCHECK_EQ( + base::apple::GetValueFromDictionary(query, kSecReturnRef), + kCFBooleanTrue); + DCHECK_EQ(base::apple::GetValueFromDictionary( + query, kSecReturnAttributes), + kCFBooleanTrue); + DCHECK_EQ( + base::apple::GetValueFromDictionary(query, kSecMatchLimit), + kSecMatchLimitAll); + + // Filter the items based on `query`. + base::apple::ScopedCFTypeRef items( + CFArrayCreateMutable(nullptr, items_.size(), &kCFTypeArrayCallBacks)); + for (auto& item : items_) { + // Each `Keychain` instance is expected to operate only on items of a single + // keychain-access-group, which is tied to the `Profile`. + CFStringRef keychain_access_group = + base::apple::GetValueFromDictionary(query, + kSecAttrAccessGroup); + DCHECK(CFEqual(keychain_access_group, + base::apple::GetValueFromDictionary( + item.get(), kSecAttrAccessGroup)) && + CFEqual(keychain_access_group, keychain_access_group_.get())); + + // Match fields present in `query`. + CFStringRef label = + base::apple::GetValueFromDictionary(query, kSecAttrLabel); + CFDataRef application_label = + base::apple::GetValueFromDictionary( + query, kSecAttrApplicationLabel); + // kSecAttrApplicationTag can be CFStringRef for legacy credentials and + // CFDataRef for new ones. We currently don't need to query for either. + DCHECK(!CFDictionaryGetValue(query, kSecAttrApplicationTag)); + if ((label && + !CFEqual(label, base::apple::GetValueFromDictionary( + item.get(), kSecAttrLabel))) || + (application_label && + !CFEqual(application_label, + base::apple::GetValueFromDictionary( + item.get(), kSecAttrApplicationLabel)))) { + continue; + } + base::apple::ScopedCFTypeRef item_copy( + CFDictionaryCreateCopy(kCFAllocatorDefault, item.get())); + CFArrayAppendValue(items.get(), item_copy.get()); + } + if (!items) { + return errSecItemNotFound; + } + *result = items.release(); + return errSecSuccess; +} + +OSStatus FakeAppleKeychainV2::ItemDelete(CFDictionaryRef query) { + // Validate certain fields that we always expect to be set. + DCHECK_EQ(base::apple::GetValueFromDictionary(query, kSecClass), + kSecClassKey); + DCHECK(CFEqual(base::apple::GetValueFromDictionary( + query, kSecAttrAccessGroup), + keychain_access_group_.get())); + // Only supporting deletion via `kSecAttrApplicationLabel` (credential ID) for + // now (see `TouchIdCredentialStore::DeleteCredentialById()`). + CFDataRef query_credential_id = + base::apple::GetValueFromDictionary(query, + kSecAttrApplicationLabel); + DCHECK(query_credential_id); + for (auto it = items_.begin(); it != items_.end(); ++it) { + const base::apple::ScopedCFTypeRef& item = *it; + CFDataRef item_credential_id = + base::apple::GetValueFromDictionary( + item.get(), kSecAttrApplicationLabel); + DCHECK(item_credential_id); + if (CFEqual(query_credential_id, item_credential_id)) { + items_.erase(it); // N.B. `it` becomes invalid + return errSecSuccess; + } + } + return errSecItemNotFound; +} + +OSStatus FakeAppleKeychainV2::ItemUpdate( + CFDictionaryRef query, + base::apple::ScopedCFTypeRef attributes_to_update) { + DCHECK_EQ(base::apple::GetValueFromDictionary(query, kSecClass), + kSecClassKey); + DCHECK(CFEqual(base::apple::GetValueFromDictionary( + query, kSecAttrAccessGroup), + keychain_access_group_.get())); + CFDataRef query_credential_id = + base::apple::GetValueFromDictionary(query, + kSecAttrApplicationLabel); + DCHECK(query_credential_id); + for (auto it = items_.begin(); it != items_.end(); ++it) { + const base::apple::ScopedCFTypeRef& item = *it; + CFDataRef item_credential_id = + base::apple::GetValueFromDictionary( + item.get(), kSecAttrApplicationLabel); + DCHECK(item_credential_id); + if (!CFEqual(query_credential_id, item_credential_id)) { + continue; + } + base::apple::ScopedCFTypeRef item_copy( + CFDictionaryCreateMutableCopy(kCFAllocatorDefault, /*capacity=*/0, + item.get())); + size_t size = CFDictionaryGetCount(attributes_to_update.get()); + std::vector keys(size, nullptr); + std::vector values(size, nullptr); + CFDictionaryGetKeysAndValues(attributes_to_update.get(), + reinterpret_cast(keys.data()), + reinterpret_cast(values.data())); + for (size_t i = 0; i < size; ++i) { + CFDictionarySetValue(item_copy.get(), keys[i], values[i]); + } + *it = base::apple::ScopedCFTypeRef(item_copy.release()); + return errSecSuccess; + } + return errSecItemNotFound; +} + +ScopedFakeAppleKeychainV2::ScopedFakeAppleKeychainV2( + const std::string& keychain_access_group) + : FakeAppleKeychainV2(keychain_access_group) { + SetInstanceOverride(this); +} + +ScopedFakeAppleKeychainV2::~ScopedFakeAppleKeychainV2() { + ClearInstanceOverride(); +} + +} // namespace crypto diff --git a/naiveproxy/src/crypto/random.cc b/naiveproxy/src/crypto/random.cc index ce4acb7429..5518112690 100644 --- a/naiveproxy/src/crypto/random.cc +++ b/naiveproxy/src/crypto/random.cc @@ -6,6 +6,8 @@ #include +#include + #include "base/rand_util.h" namespace crypto { @@ -21,5 +23,11 @@ void RandBytes(base::span bytes) { RandBytes(bytes.data(), bytes.size()); } +std::vector RandBytesAsVector(size_t length) { + std::vector result(length); + RandBytes(result); + return result; +} + } // namespace crypto diff --git a/naiveproxy/src/crypto/random.h b/naiveproxy/src/crypto/random.h index 2927c923a8..af904b2909 100644 --- a/naiveproxy/src/crypto/random.h +++ b/naiveproxy/src/crypto/random.h @@ -7,18 +7,23 @@ #include +#include + #include "base/containers/span.h" #include "crypto/crypto_export.h" namespace crypto { -// Fills the given buffer with |length| random bytes of cryptographically +// Fills the given buffer with `length` random bytes of cryptographically // secure random numbers. -// |length| must be positive. CRYPTO_EXPORT void RandBytes(void *bytes, size_t length); -// Fills |bytes| with cryptographically-secure random bits. +// Fills `bytes` with cryptographically-secure random bits. CRYPTO_EXPORT void RandBytes(base::span bytes); + +// Returns a vector of `length` bytes filled with cryptographically-secure +// random bits. +CRYPTO_EXPORT std::vector RandBytesAsVector(size_t length); } #endif // CRYPTO_RANDOM_H_ diff --git a/naiveproxy/src/crypto/symmetric_key.cc b/naiveproxy/src/crypto/symmetric_key.cc index c8aa5171ae..4c4e0592e9 100644 --- a/naiveproxy/src/crypto/symmetric_key.cc +++ b/naiveproxy/src/crypto/symmetric_key.cc @@ -12,7 +12,6 @@ #include "base/check_op.h" #include "base/notreached.h" -#include "base/strings/string_util.h" #include "crypto/openssl_util.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rand.h" @@ -61,10 +60,10 @@ std::unique_ptr SymmetricKey::GenerateRandomKey( OpenSSLErrStackTracer err_tracer(FROM_HERE); std::unique_ptr key(new SymmetricKey); - uint8_t* key_data = reinterpret_cast( - base::WriteInto(&key->key_, key_size_in_bytes + 1)); - int rv = RAND_bytes(key_data, static_cast(key_size_in_bytes)); + key->key_.resize(key_size_in_bytes); + int rv = RAND_bytes(reinterpret_cast(key->key_.data()), + key->key_.size()); return rv == 1 ? std::move(key) : nullptr; } @@ -82,14 +81,12 @@ std::unique_ptr SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2( OpenSSLErrStackTracer err_tracer(FROM_HERE); std::unique_ptr key(new SymmetricKey); - uint8_t* key_data = reinterpret_cast( - base::WriteInto(&key->key_, key_size_in_bytes + 1)); - + key->key_.resize(key_size_in_bytes); int rv = PKCS5_PBKDF2_HMAC_SHA1( password.data(), password.length(), reinterpret_cast(salt.data()), salt.length(), - static_cast(iterations), - key_size_in_bytes, key_data); + static_cast(iterations), key->key_.size(), + reinterpret_cast(key->key_.data())); return rv == 1 ? std::move(key) : nullptr; } @@ -110,14 +107,12 @@ std::unique_ptr SymmetricKey::DeriveKeyFromPasswordUsingScrypt( OpenSSLErrStackTracer err_tracer(FROM_HERE); std::unique_ptr key(new SymmetricKey); - uint8_t* key_data = reinterpret_cast( - base::WriteInto(&key->key_, key_size_in_bytes + 1)); - - int rv = EVP_PBE_scrypt(password.data(), password.length(), - reinterpret_cast(salt.data()), - salt.length(), cost_parameter, block_size, - parallelization_parameter, max_memory_bytes, key_data, - key_size_in_bytes); + key->key_.resize(key_size_in_bytes); + int rv = EVP_PBE_scrypt( + password.data(), password.length(), + reinterpret_cast(salt.data()), salt.length(), + cost_parameter, block_size, parallelization_parameter, max_memory_bytes, + reinterpret_cast(key->key_.data()), key->key_.size()); return rv == 1 ? std::move(key) : nullptr; } diff --git a/naiveproxy/src/crypto/user_verifying_key.cc b/naiveproxy/src/crypto/user_verifying_key.cc new file mode 100644 index 0000000000..02cec3db07 --- /dev/null +++ b/naiveproxy/src/crypto/user_verifying_key.cc @@ -0,0 +1,27 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "crypto/user_verifying_key.h" + +#include "base/check.h" +#include "base/functional/bind.h" + +namespace crypto { + +UserVerifyingSigningKey::~UserVerifyingSigningKey() = default; +UserVerifyingKeyProvider::~UserVerifyingKeyProvider() = default; + +#if BUILDFLAG(IS_WIN) +std::unique_ptr GetUserVerifyingKeyProviderWin(); +#endif + +std::unique_ptr GetUserVerifyingKeyProvider() { +#if BUILDFLAG(IS_WIN) + return GetUserVerifyingKeyProviderWin(); +#else + return nullptr; +#endif +} + +} // namespace crypto diff --git a/naiveproxy/src/crypto/user_verifying_key.h b/naiveproxy/src/crypto/user_verifying_key.h new file mode 100644 index 0000000000..29688fbbf9 --- /dev/null +++ b/naiveproxy/src/crypto/user_verifying_key.h @@ -0,0 +1,100 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CRYPTO_USER_VERIFYING_KEY_H_ +#define CRYPTO_USER_VERIFYING_KEY_H_ + +#include +#include +#include +#include + +#include "base/containers/span.h" +#include "base/functional/callback.h" +#include "build/build_config.h" +#include "crypto/crypto_export.h" +#include "crypto/signature_verifier.h" + +namespace crypto { + +// The type of the identifiers for user-verifying keys depends on the +// underlying platform API. +#if BUILDFLAG(IS_WIN) +typedef std::string UserVerifyingKeyLabel; +#else +typedef int UserVerifyingKeyLabel; // Unused. +#endif + +// UserVerifyingSigningKey is a hardware-backed key that triggers a user +// verification by the platform before a signature will be provided. +// +// Notes: +// - This is currently only supported on Windows. +// - This does not export a wrapped key because it uses the WinRT +// KeyCredentialManager which addresses stored keys by name. +// - The interface for this class will likely need to be generalized as support +// for other platforms is added. +class CRYPTO_EXPORT UserVerifyingSigningKey { + public: + virtual ~UserVerifyingSigningKey(); + + // Sign invokes |callback| to provide a signature of |data|, or |nullopt| if + // an error occurs during signing. + virtual void Sign( + base::span data, + base::OnceCallback>)> + callback) = 0; + + // Provides the SPKI public key. + virtual std::vector GetPublicKey() const = 0; + + // Get a reference to the label used to create or retrieve this key. + virtual const UserVerifyingKeyLabel& GetKeyLabel() const = 0; +}; + +// UserVerifyingKeyProvider creates |UserVerifyingSigningKey|s. +// Only one call to |GenerateUserVerifyingSigningKey| or +// |GetUserVerifyingSigningKey| can be outstanding at one time for a single +// provider, but multiple providers can be used. Destroying a provider will +// cancel an outstanding key generation or retrieval and delete the callback +// without running it. +class CRYPTO_EXPORT UserVerifyingKeyProvider { + public: + virtual ~UserVerifyingKeyProvider(); + + // Similar to |GenerateSigningKeySlowly| but the resulting signing key can + // only be used with a local user authentication by the platform. This can be + // called from any thread as the work is done asynchronously on a + // low-priority thread. + // Invokes |callback| with the resulting key, or nullptr on error. + // + // This is currently only supported on Windows. + virtual void GenerateUserVerifyingSigningKey( + UserVerifyingKeyLabel key_label, + base::span + acceptable_algorithms, + base::OnceCallback)> + callback) = 0; + + // Similar to |FromWrappedSigningKey| but uses a wrapped key that was + // generated from |GenerateUserVerifyingSigningKey|. This can be called from + // any thread as the work is done asynchronously on a low-priority thread. + // Invokes |callback| with the resulting key, or nullptr on error. + // + // This is currently only supported on Windows. + virtual void GetUserVerifyingSigningKey( + UserVerifyingKeyLabel key_label, + base::OnceCallback)> + callback) = 0; +}; + +// GetUserVerifyingKeyProvider returns |UserVerifyingKeyProvider| for the +// current platform, or nullptr if this is not implemented on the current +// platform. +CRYPTO_EXPORT std::unique_ptr +GetUserVerifyingKeyProvider(); + +} // namespace crypto + +#endif // CRYPTO_USER_VERIFYING_KEY_H_ diff --git a/naiveproxy/src/crypto/user_verifying_key_win.cc b/naiveproxy/src/crypto/user_verifying_key_win.cc new file mode 100644 index 0000000000..3c9550d5dc --- /dev/null +++ b/naiveproxy/src/crypto/user_verifying_key_win.cc @@ -0,0 +1,465 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +#include +#include +#include +#include + +#include "base/logging.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/task/thread_pool.h" +#include "base/threading/scoped_thread_priority.h" +#include "base/win/core_winrt_util.h" +#include "base/win/post_async_results.h" +#include "base/win/scoped_hstring.h" +#include "base/win/winrt_storage_util.h" +#include "crypto/user_verifying_key.h" + +using ABI::Windows::Foundation::IAsyncOperation; +using ABI::Windows::Security::Credentials::IKeyCredential; +using ABI::Windows::Security::Credentials::IKeyCredentialManagerStatics; +using ABI::Windows::Security::Credentials::IKeyCredentialOperationResult; +using ABI::Windows::Security::Credentials::IKeyCredentialRetrievalResult; +using ABI::Windows::Security::Credentials::KeyCredentialCreationOption; +using ABI::Windows::Security::Credentials::KeyCredentialOperationResult; +using ABI::Windows::Security::Credentials::KeyCredentialRetrievalResult; +using ABI::Windows::Security::Credentials::KeyCredentialStatus; +using ABI::Windows::Security::Credentials::KeyCredentialStatus_Success; +using ABI::Windows::Security::Cryptography::Core:: + CryptographicPublicKeyBlobType_X509SubjectPublicKeyInfo; +using ABI::Windows::Storage::Streams::IBuffer; +using Microsoft::WRL::ComPtr; + +namespace crypto { + +namespace { + +// These helpers wrap callbacks by posting them to the original calling thread. +// This enables the wrapped callbacks to bind weak pointers. +template +base::OnceCallback WrapOnceCallbackForCallingThread( + scoped_refptr caller_task_runner, + base::OnceCallback callback) { + return base::BindOnce( + [](scoped_refptr caller_task_runner, + base::OnceCallback callback, Arg result) { + caller_task_runner->PostTask( + FROM_HERE, + base::BindOnce([](base::OnceCallback callback, + Arg result) { std::move(callback).Run(result); }, + std::move(callback), result)); + }, + caller_task_runner, std::move(callback)); +} + +template +base::RepeatingCallback WrapRepeatingCallbackForCallingThread( + scoped_refptr caller_task_runner, + base::RepeatingCallback callback) { + return base::BindRepeating( + [](scoped_refptr caller_task_runner, + base::RepeatingCallback callback, Arg result) { + caller_task_runner->PostTask( + FROM_HERE, + base::BindRepeating([](base::RepeatingCallback callback, + Arg result) { callback.Run(result); }, + std::move(callback), result)); + }, + caller_task_runner, std::move(callback)); +} + +std::optional SelectAlgorithm( + base::span + acceptable_algorithms) { + // Windows keys come in any algorithm you want, as long as it's RSA 2048. + for (auto algorithm : acceptable_algorithms) { + if (algorithm == SignatureVerifier::SignatureAlgorithm::RSA_PKCS1_SHA256) { + return algorithm; + } + } + return std::nullopt; +} + +void SignInternal( + std::vector data, + ComPtr credential, + base::OnceCallback)> + success_callback, + base::RepeatingCallback error_callback) { + Microsoft::WRL::ComPtr signing_buf; + HRESULT hr = + base::win::CreateIBufferFromData(data.data(), data.size(), &signing_buf); + if (FAILED(hr)) { + LOG(ERROR) << "SignInternal: IBuffer creation failed."; + error_callback.Run(hr); + return; + } + + ComPtr> sign_result; + hr = credential->RequestSignAsync(signing_buf.Get(), &sign_result); + if (FAILED(hr)) { + LOG(ERROR) << "SignInternal: Call to RequestSignAsync failed."; + error_callback.Run(hr); + return; + } + + hr = base::win::PostAsyncHandlers( + sign_result.Get(), std::move(success_callback), + base::BindOnce([](base::RepeatingCallback cb, + HRESULT hr) { cb.Run(hr); }, + error_callback)); + if (FAILED(hr)) { + LOG(ERROR) << "SignInternal: Call to PostAsyncHandlers failed."; + error_callback.Run(hr); + return; + } +} + +class UserVerifyingSigningKeyWin : public UserVerifyingSigningKey { + public: + UserVerifyingSigningKeyWin(std::string key_name, + ComPtr credential) + : key_name_(std::move(key_name)), credential_(std::move(credential)) {} + ~UserVerifyingSigningKeyWin() override = default; + + void Sign(base::span data, + base::OnceCallback>)> + callback) override { + CHECK(!signing_callback_); + scoped_refptr task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); + signing_callback_ = std::move(callback); + scoped_refptr caller_task_runner = + base::SingleThreadTaskRunner::GetCurrentDefault(); + auto success_callback = + WrapOnceCallbackForCallingThread>( + caller_task_runner, + base::BindOnce(&UserVerifyingSigningKeyWin::OnSigningSuccess, + weak_factory_.GetWeakPtr())); + auto error_callback = WrapRepeatingCallbackForCallingThread( + caller_task_runner, + base::BindRepeating(&UserVerifyingSigningKeyWin::OnSigningError, + weak_factory_.GetWeakPtr())); + std::vector vec_data(data.begin(), data.end()); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(&SignInternal, std::move(vec_data), credential_, + std::move(success_callback), std::move(error_callback))); + } + + std::vector GetPublicKey() const override { + ComPtr key_buf; + HRESULT hr = credential_->RetrievePublicKeyWithBlobType( + CryptographicPublicKeyBlobType_X509SubjectPublicKeyInfo, &key_buf); + CHECK(SUCCEEDED(hr)) + << "Failed to obtain public key from KeyCredential, hr = " + << logging::SystemErrorCodeToString(hr); + + uint8_t* pub_key_data = nullptr; + uint32_t pub_key_length = 0; + hr = base::win::GetPointerToBufferData(key_buf.Get(), &pub_key_data, + &pub_key_length); + CHECK(SUCCEEDED(hr)) << "Failed to access public key buffer data, hr = " + << logging::SystemErrorCodeToString(hr); + return std::vector(pub_key_data, pub_key_data + pub_key_length); + } + + const UserVerifyingKeyLabel& GetKeyLabel() const override { + return key_name_; + } + + private: + void OnSigningSuccess(ComPtr sign_result) { + // This SHOULD only be called once but conservatively we ignore additional + // calls to reduce assumptions of good behaviour by the platform APIs. + if (!signing_callback_) { + return; + } + + KeyCredentialStatus status; + HRESULT hr = sign_result->get_Status(&status); + if (FAILED(hr) || status != KeyCredentialStatus_Success) { + LOG(ERROR) << "Failed to obtain Status from " + "IKeyCredentialOperationResult, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(signing_callback_).Run(std::nullopt); + return; + } + + ComPtr signature_buffer; + hr = sign_result->get_Result(&signature_buffer); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to obtain Result from " + "IKeyCredentialOperationResult, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(signing_callback_).Run(std::nullopt); + return; + } + + uint8_t* signature_data = nullptr; + uint32_t signature_length = 0; + hr = base::win::GetPointerToBufferData(signature_buffer.Get(), + &signature_data, &signature_length); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to obtain data from " + "signature buffer, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(signing_callback_).Run(std::nullopt); + return; + } + std::move(signing_callback_) + .Run(std::vector(signature_data, + signature_data + signature_length)); + } + + void OnSigningError(HRESULT hr) { + // This SHOULD only be called once but conservatively we ignore additional + // calls to reduce assumptions of good behaviour by the platform APIs. + if (!signing_callback_) { + return; + } + LOG(ERROR) << "Failed to sign with user-verifying signature, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(signing_callback_).Run(std::nullopt); + } + + std::string key_name_; + ComPtr credential_; + + base::OnceCallback>)> + signing_callback_; + + base::WeakPtrFactory weak_factory_{this}; +}; + +void GenerateUserVerifyingSigningKeyInternal( + base::win::ScopedHString key_name, + base::OnceCallback)> + success_callback, + base::RepeatingCallback error_callback) { + SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); + + ComPtr factory; + HRESULT hr = base::win::GetActivationFactory< + IKeyCredentialManagerStatics, + RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory); + if (FAILED(hr)) { + LOG(ERROR) << "GenerateUserVerifyingSigningKeyInternal: Failed to obtain " + "activation factory for KeyCredentialManager."; + error_callback.Run(hr); + return; + } + + ComPtr> create_result; + hr = factory->RequestCreateAsync( + key_name.get(), + KeyCredentialCreationOption::KeyCredentialCreationOption_ReplaceExisting, + &create_result); + if (FAILED(hr)) { + LOG(ERROR) << "GenerateUserVerifyingSigningKeyInternal: Call to " + "RequestCreateAsync failed."; + error_callback.Run(hr); + return; + } + + hr = base::win::PostAsyncHandlers( + create_result.Get(), std::move(success_callback), + base::BindOnce([](base::RepeatingCallback cb, + HRESULT hr) { cb.Run(hr); }, + error_callback)); + if (FAILED(hr)) { + LOG(ERROR) << "GenerateUserVerifyingSigningKeyInternal: Call to " + "PostAsyncHandlers failed."; + error_callback.Run(hr); + return; + } +} + +void GetUserVerifyingSigningKeyInternal( + base::win::ScopedHString key_name, + base::OnceCallback)> + success_callback, + base::RepeatingCallback error_callback) { + SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); + + ComPtr factory; + HRESULT hr = base::win::GetActivationFactory< + IKeyCredentialManagerStatics, + RuntimeClass_Windows_Security_Credentials_KeyCredentialManager>(&factory); + if (FAILED(hr)) { + LOG(ERROR) << "GetUserVerifyingSigningKeyInternal: Failed to obtain " + "activation factory for KeyCredentialManager."; + error_callback.Run(hr); + return; + } + + ComPtr> open_result; + hr = factory->OpenAsync(key_name.get(), &open_result); + if (FAILED(hr)) { + LOG(ERROR) + << "GetUserVerifyingSigningKeyInternal: Call to OpenAsync failed."; + error_callback.Run(hr); + return; + } + + hr = base::win::PostAsyncHandlers( + open_result.Get(), std::move(success_callback), + base::BindOnce([](base::RepeatingCallback cb, + HRESULT hr) { cb.Run(hr); }, + error_callback)); + if (FAILED(hr)) { + LOG(ERROR) << "GetUserVerifyingSigningKeyInternal: Call to " + "PostAsyncHandlers failed."; + error_callback.Run(hr); + return; + } +} + +class UserVerifyingKeyProviderWin : public UserVerifyingKeyProvider { + public: + UserVerifyingKeyProviderWin() = default; + ~UserVerifyingKeyProviderWin() override = default; + + void GenerateUserVerifyingSigningKey( + UserVerifyingKeyLabel key_label, + base::span + acceptable_algorithms, + base::OnceCallback)> + callback) override { + CHECK(!key_creation_callback_); + + // Ignore the non-empty return value of `SelectAlgorithm` unless in the + // future Windows supports more algorithms. + if (!SelectAlgorithm(acceptable_algorithms)) { + LOG(ERROR) << "Key generation does not include a supported algorithm."; + std::move(callback).Run(nullptr); + return; + } + + auto key_name = base::win::ScopedHString::Create(key_label); + scoped_refptr task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); + key_creation_callback_ = std::move(callback); + scoped_refptr caller_task_runner = + base::SingleThreadTaskRunner::GetCurrentDefault(); + auto success_callback = + WrapOnceCallbackForCallingThread>( + caller_task_runner, + base::BindOnce( + &UserVerifyingKeyProviderWin::OnKeyCreationCompletionSuccess, + weak_factory_.GetWeakPtr(), std::move(key_label))); + auto error_callback = WrapRepeatingCallbackForCallingThread( + caller_task_runner, + base::BindRepeating( + &UserVerifyingKeyProviderWin::OnKeyCreationCompletionError, + weak_factory_.GetWeakPtr())); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(&GenerateUserVerifyingSigningKeyInternal, + std::move(key_name), std::move(success_callback), + std::move(error_callback))); + } + + void GetUserVerifyingSigningKey( + UserVerifyingKeyLabel key_label, + base::OnceCallback)> + callback) override { + CHECK(!key_creation_callback_); + auto key_name = base::win::ScopedHString::Create(key_label); + scoped_refptr task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); + key_creation_callback_ = std::move(callback); + scoped_refptr caller_task_runner = + base::SingleThreadTaskRunner::GetCurrentDefault(); + auto success_callback = + WrapOnceCallbackForCallingThread>( + caller_task_runner, + base::BindOnce( + &UserVerifyingKeyProviderWin::OnKeyCreationCompletionSuccess, + weak_factory_.GetWeakPtr(), std::move(key_label))); + auto error_callback = WrapRepeatingCallbackForCallingThread( + caller_task_runner, + base::BindRepeating( + &UserVerifyingKeyProviderWin::OnKeyCreationCompletionError, + weak_factory_.GetWeakPtr())); + task_runner->PostTask( + FROM_HERE, + base::BindOnce(&GetUserVerifyingSigningKeyInternal, std::move(key_name), + std::move(success_callback), std::move(error_callback))); + } + + private: + void OnKeyCreationCompletionSuccess( + std::string key_name, + ComPtr key_result) { + // This SHOULD only be called once but conservatively we ignore additional + // calls to reduce assumptions of good behaviour by the platform APIs. + if (!key_creation_callback_) { + return; + } + + KeyCredentialStatus status; + HRESULT hr = key_result->get_Status(&status); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to obtain Status from " + "IKeyCredentialRetrievalResult, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(key_creation_callback_).Run(nullptr); + return; + } else if (status != KeyCredentialStatus_Success) { + LOG(ERROR) << "IKeyCredentialRetrievalResult status is " + << static_cast(status); + std::move(key_creation_callback_).Run(nullptr); + return; + } + + ComPtr credential; + hr = key_result->get_Credential(&credential); + if (FAILED(hr)) { + LOG(ERROR) << "Failed to obtain KeyCredential from " + "KeyCredentialRetrievalResult, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(key_creation_callback_).Run(nullptr); + return; + } + auto key = std::make_unique( + std::move(key_name), std::move(credential)); + std::move(key_creation_callback_).Run(std::move(key)); + } + + void OnKeyCreationCompletionError(HRESULT hr) { + // This SHOULD only be called once but conservatively we ignore additional + // calls to reduce assumptions of good behaviour by the platform APIs. + if (!key_creation_callback_) { + return; + } + LOG(ERROR) << "Failed to obtain user-verifying key from system, hr = " + << logging::SystemErrorCodeToString(hr); + std::move(key_creation_callback_).Run(nullptr); + } + + // This has to be cached here rather than bound as an argument + // `KeyCreationCallback` because we have to use multiple callbacks + // internally. Windows async APIs take separate callbacks for success and + // failure, and a `OnceCallback` can't be bound to both. + base::OnceCallback)> + key_creation_callback_; + + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace + +std::unique_ptr GetUserVerifyingKeyProviderWin() { + return std::make_unique(); +} + +} // namespace crypto diff --git a/naiveproxy/src/get-openwrt.sh b/naiveproxy/src/get-openwrt.sh index 7919df382b..4ae0056172 100755 --- a/naiveproxy/src/get-openwrt.sh +++ b/naiveproxy/src/get-openwrt.sh @@ -48,3 +48,8 @@ tar cf - -C $full_root --hard-dereference . | tar xf - -C $sysroot --wildcards - rm -rf include.txt cd .. rm -rf $SDK_PATH + +# LLVM does not accept muslgnueabi as the target triple environment +if [ -d "$sysroot/lib/gcc/arm-openwrt-linux-muslgnueabi" ]; then + mv "$sysroot/lib/gcc/arm-openwrt-linux-muslgnueabi" "$sysroot/lib/gcc/arm-openwrt-linux-musleabi" +fi diff --git a/naiveproxy/src/net/BUILD.gn b/naiveproxy/src/net/BUILD.gn index 8eff04e222..a183cd50dc 100644 --- a/naiveproxy/src/net/BUILD.gn +++ b/naiveproxy/src/net/BUILD.gn @@ -259,6 +259,7 @@ component("net") { "base/scheme_host_port_matcher_rule.h", "base/schemeful_site.cc", "base/schemeful_site.h", + "base/session_usage.h", "base/sockaddr_storage.cc", "base/sockaddr_storage.h", "base/sys_addrinfo.h", @@ -790,12 +791,18 @@ component("net") { "quic/quic_http_utils.h", "quic/quic_proxy_client_socket.cc", "quic/quic_proxy_client_socket.h", + "quic/quic_proxy_datagram_client_socket.cc", + "quic/quic_proxy_datagram_client_socket.h", "quic/quic_server_info.cc", "quic/quic_server_info.h", "quic/quic_session_key.cc", "quic/quic_session_key.h", "quic/quic_session_pool.cc", "quic/quic_session_pool.h", + "quic/quic_session_pool_direct_job.cc", + "quic/quic_session_pool_direct_job.h", + "quic/quic_session_pool_job.cc", + "quic/quic_session_pool_job.h", "quic/set_quic_flag.cc", "quic/set_quic_flag.h", "quic/web_transport_client.cc", @@ -995,11 +1002,6 @@ component("net") { "url_request/url_request_netlog_params.h", "url_request/url_request_redirect_job.cc", "url_request/url_request_redirect_job.h", - "url_request/url_request_throttler_entry.cc", - "url_request/url_request_throttler_entry.h", - "url_request/url_request_throttler_entry_interface.h", - "url_request/url_request_throttler_manager.cc", - "url_request/url_request_throttler_manager.h", "url_request/view_cache_helper.cc", "url_request/view_cache_helper.h", "url_request/websocket_handshake_userdata_key.cc", @@ -1179,7 +1181,6 @@ component("net") { sources += [ "base/apple/url_conversions.h", "base/apple/url_conversions.mm", - "base/mac/url_conversions.h", "base/network_change_notifier_apple.h", "base/network_change_notifier_apple.mm", "base/network_config_watcher_apple.cc", diff --git a/naiveproxy/src/net/PRESUBMIT.py b/naiveproxy/src/net/PRESUBMIT.py index 6c47b9d8ba..0e39c8d520 100644 --- a/naiveproxy/src/net/PRESUBMIT.py +++ b/naiveproxy/src/net/PRESUBMIT.py @@ -27,11 +27,6 @@ def CheckChange(input_api, output_api): output_api, 'data/test_support_bundle_data', globroot='.') - results += presubmit_support.CheckBundleData( - input_api, - output_api, - 'third_party/nist-pkits/test_bundle_data', - globroot='third_party/nist-pkits') finally: sys.path = old_sys_path return results diff --git a/naiveproxy/src/net/android/dummy_spnego_authenticator.cc b/naiveproxy/src/net/android/dummy_spnego_authenticator.cc index d7573d7417..3c19ce5fc6 100644 --- a/naiveproxy/src/net/android/dummy_spnego_authenticator.cc +++ b/naiveproxy/src/net/android/dummy_spnego_authenticator.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "net/android/dummy_spnego_authenticator.h" +#include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/base64.h" #include "net/android/net_test_support_provider_jni/DummySpnegoAuthenticator_jni.h" diff --git a/naiveproxy/src/net/android/keystore.cc b/naiveproxy/src/net/android/keystore.cc index f840555647..15fc00725d 100644 --- a/naiveproxy/src/net/android/keystore.cc +++ b/naiveproxy/src/net/android/keystore.cc @@ -67,8 +67,7 @@ bool SignWithPrivateKey(const JavaRef& private_key_ref, DCHECK(!algorithm_ref.is_null()); // Convert message to byte[] array. - ScopedJavaLocalRef input_ref = - ToJavaByteArray(env, input.data(), input.size()); + ScopedJavaLocalRef input_ref = ToJavaByteArray(env, input); DCHECK(!input_ref.is_null()); // Invoke platform API @@ -94,8 +93,7 @@ bool EncryptWithPrivateKey(const JavaRef& private_key_ref, DCHECK(!algorithm_ref.is_null()); // Convert message to byte[] array. - ScopedJavaLocalRef input_ref = - ToJavaByteArray(env, input.data(), input.size()); + ScopedJavaLocalRef input_ref = ToJavaByteArray(env, input); DCHECK(!input_ref.is_null()); // Invoke platform API diff --git a/naiveproxy/src/net/android/network_library.cc b/naiveproxy/src/net/android/network_library.cc index fd81dedcb3..d4ae0db1dd 100644 --- a/naiveproxy/src/net/android/network_library.cc +++ b/naiveproxy/src/net/android/network_library.cc @@ -140,12 +140,12 @@ void SetWifiEnabledForTesting(bool enabled) { base::android::AttachCurrentThread(), enabled); } -absl::optional GetWifiSignalLevel() { +std::optional GetWifiSignalLevel() { const int count_buckets = 5; int signal_strength = Java_AndroidNetworkLibrary_getWifiSignalLevel( base::android::AttachCurrentThread(), count_buckets); if (signal_strength < 0) - return absl::nullopt; + return std::nullopt; DCHECK_LE(0, signal_strength); DCHECK_GE(count_buckets - 1, signal_strength); diff --git a/naiveproxy/src/net/android/network_library.h b/naiveproxy/src/net/android/network_library.h index 7437793020..51191c5a11 100644 --- a/naiveproxy/src/net/android/network_library.h +++ b/naiveproxy/src/net/android/network_library.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -22,7 +23,6 @@ #include "net/base/net_export.h" #include "net/base/network_handle.h" #include "net/socket/socket_descriptor.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net::android { @@ -90,7 +90,7 @@ NET_EXPORT_PRIVATE void SetWifiEnabledForTesting(bool enabled); // Returns the signal strength level (between 0 and 4, both inclusive) of the // currently registered Wifi connection. If the value is unavailable, an // empty value is returned. -NET_EXPORT_PRIVATE absl::optional GetWifiSignalLevel(); +NET_EXPORT_PRIVATE std::optional GetWifiSignalLevel(); // Gets the DNS servers for the current default network and puts them in // `dns_servers`. Sets `dns_over_tls_active` and `dns_over_tls_hostname` based diff --git a/naiveproxy/src/net/android/traffic_stats.cc b/naiveproxy/src/net/android/traffic_stats.cc index 53a6e6b589..c5b3a7b7ce 100644 --- a/naiveproxy/src/net/android/traffic_stats.cc +++ b/naiveproxy/src/net/android/traffic_stats.cc @@ -16,25 +16,25 @@ enum TrafficStatsError { }; bool GetTotalTxBytes(int64_t* bytes) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); *bytes = Java_AndroidTrafficStats_getTotalTxBytes(env); return *bytes != ERROR_NOT_SUPPORTED; } bool GetTotalRxBytes(int64_t* bytes) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); *bytes = Java_AndroidTrafficStats_getTotalRxBytes(env); return *bytes != ERROR_NOT_SUPPORTED; } bool GetCurrentUidTxBytes(int64_t* bytes) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); *bytes = Java_AndroidTrafficStats_getCurrentUidTxBytes(env); return *bytes != ERROR_NOT_SUPPORTED; } bool GetCurrentUidRxBytes(int64_t* bytes) { - JNIEnv* env = base::android::AttachCurrentThread(); + JNIEnv* env = jni_zero::AttachCurrentThread(); *bytes = Java_AndroidTrafficStats_getCurrentUidRxBytes(env); return *bytes != ERROR_NOT_SUPPORTED; } diff --git a/naiveproxy/src/net/android/unittest_support/AndroidManifest.xml b/naiveproxy/src/net/android/unittest_support/AndroidManifest.xml index 43cc4ea95d..00286bb64d 100644 --- a/naiveproxy/src/net/android/unittest_support/AndroidManifest.xml +++ b/naiveproxy/src/net/android/unittest_support/AndroidManifest.xml @@ -57,7 +57,6 @@ found in the LICENSE file. + android:label="Instrumentation entry point for org.chromium.native_test" /> diff --git a/naiveproxy/src/net/base/address_tracker_linux.cc b/naiveproxy/src/net/base/address_tracker_linux.cc index 1a18bc41b9..3884057ddd 100644 --- a/naiveproxy/src/net/base/address_tracker_linux.cc +++ b/naiveproxy/src/net/base/address_tracker_linux.cc @@ -501,7 +501,7 @@ void AddressTrackerLinux::HandleMessage(const char* buffer, // changed. auto it = address_map_.find(address); if (it == address_map_.end()) { - address_map_.insert(it, std::make_pair(address, msg_copy)); + address_map_.insert(it, std::pair(address, msg_copy)); *address_changed = true; } else if (memcmp(&it->second, &msg_copy, sizeof(msg_copy))) { it->second = msg_copy; diff --git a/naiveproxy/src/net/base/expiring_cache.h b/naiveproxy/src/net/base/expiring_cache.h index 567c63ac59..a6f14a5d53 100644 --- a/naiveproxy/src/net/base/expiring_cache.h +++ b/naiveproxy/src/net/base/expiring_cache.h @@ -152,7 +152,7 @@ class ExpiringCache { Compact(now); // No existing entry. Creating a new one. - entries_.insert(std::make_pair(key, Entry(value, expiration))); + entries_.insert(std::pair(key, Entry(value, expiration))); } else { // Update an existing cache entry. it->second.first = value; diff --git a/naiveproxy/src/net/base/features.cc b/naiveproxy/src/net/base/features.cc index 84235adad4..5c1d1769ee 100644 --- a/naiveproxy/src/net/base/features.cc +++ b/naiveproxy/src/net/base/features.cc @@ -23,6 +23,16 @@ BASE_FEATURE(kCapReferrerToOriginOnCrossOrigin, "CapReferrerToOriginOnCrossOrigin", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kAsyncDns, + "AsyncDns", +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) || \ + BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +); + BASE_FEATURE(kDnsTransactionDynamicTimeouts, "DnsTransactionDynamicTimeouts", base::FEATURE_DISABLED_BY_DEFAULT); @@ -67,6 +77,10 @@ BASE_FEATURE(kUseDnsHttpsSvcbAlpn, "UseDnsHttpsSvcbAlpn", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kUseHostResolverCache, + "UseHostResolverCache", + base::FEATURE_DISABLED_BY_DEFAULT); + const base::FeatureParam kAlternativePortForGloballyReachableCheck{ &kUseAlternativePortForGloballyReachableCheck, "AlternativePortForGloballyReachableCheck", 443}; @@ -396,18 +410,10 @@ const base::FeatureParam kIpPrivacyDirectOnly{ &kEnableIpProtectionProxy, /*name=*/"IpPrivacyDirectOnly", /*default_value=*/false}; -const base::FeatureParam kIpPrivacyBsaEnablePrivacyPass{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyBsaEnablePrivacyPass", - /*default_value=*/false}; - const base::FeatureParam kIpPrivacyProxyBPsk{ &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyBPsk", /*default_value=*/""}; -const base::FeatureParam kIpPrivacyUseProxyChains{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyUseProxyChains", - /*default_value=*/false}; - const base::FeatureParam kIpPrivacyIncludeOAuthTokenInGetProxyConfig{ &kEnableIpProtectionProxy, /*name=*/"IpPrivacyIncludeOAuthTokenInGetProxyConfig", @@ -425,6 +431,10 @@ const base::FeatureParam kIpPrivacyAddHeaderToProxiedRequests{ &kEnableIpProtectionProxy, /*name=*/"IpPrivacyAddHeaderToProxiedRequests", /*default_value=*/false}; +const base::FeatureParam kIpPrivacyExpirationFuzz{ + &kEnableIpProtectionProxy, /*name=*/"IpPrivacyExpirationFuzz", + /*default_value=*/base::Minutes(15)}; + // Network-change migration requires NetworkHandle support, which are currently // only supported on Android (see // NetworkChangeNotifier::AreNetworkHandlesSupported). @@ -483,7 +493,7 @@ BASE_FEATURE(kEnableWebTransportDraft07, BASE_FEATURE(kZstdContentEncoding, "ZstdContentEncoding", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // When enabled, partitioned storage will be allowed even if third-party cookies // are disabled by default. Partitioned storage will not be allowed if @@ -520,4 +530,8 @@ BASE_FEATURE(kTreatHTTPExpiresHeaderValueZeroAsExpired, "TreatHTTPExpiresHeaderValueZeroAsExpired", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kTruncateBodyToContentLength, + "TruncateBodyToContentLength", + base::FEATURE_ENABLED_BY_DEFAULT); + } // namespace net::features diff --git a/naiveproxy/src/net/base/features.h b/naiveproxy/src/net/base/features.h index f4afe84de8..4ddcf7af5a 100644 --- a/naiveproxy/src/net/base/features.h +++ b/naiveproxy/src/net/base/features.h @@ -30,6 +30,9 @@ NET_EXPORT BASE_DECLARE_FEATURE(kAvoidH2Reprioritization); // origin requests are restricted to contain at most the source origin. NET_EXPORT BASE_DECLARE_FEATURE(kCapReferrerToOriginOnCrossOrigin); +// Enables the built-in DNS resolver. +NET_EXPORT BASE_DECLARE_FEATURE(kAsyncDns); + // Support for altering the parameters used for DNS transaction timeout. See // ResolveContext::SecureTransactionTimeout(). NET_EXPORT BASE_DECLARE_FEATURE(kDnsTransactionDynamicTimeouts); @@ -87,6 +90,13 @@ NET_EXPORT extern const base::FeatureParam // Update protocol using ALPN information in HTTPS DNS records. NET_EXPORT BASE_DECLARE_FEATURE(kUseDnsHttpsSvcbAlpn); +// If enabled, HostResolver will use the new HostResolverCache that separately +// caches by DNS type, unlike the old HostCache that always cached by merged +// request results. May enable related behavior such as separately sorting DNS +// results after each transaction rather than sorting collectively after all +// transactions complete. +NET_EXPORT BASE_DECLARE_FEATURE(kUseHostResolverCache); + // If the `kUseAlternativePortForGloballyReachableCheck` flag is enabled, the // globally reachable check will use the port number specified by // `kAlternativePortForGloballyReachableCheck` flag. Otherwise, the globally @@ -418,18 +428,10 @@ NET_EXPORT extern const base::FeatureParam // connections that _would_ have been proxied, but were not. NET_EXPORT extern const base::FeatureParam kIpPrivacyDirectOnly; -// Controls whether the BlindSignAuth library used by IP Protection should use -// the privacy pass token format. -NET_EXPORT extern const base::FeatureParam kIpPrivacyBsaEnablePrivacyPass; - // The PSK added to connections to proxyB with `Proxy-Authorization: Preshared // $PSK`. NET_EXPORT extern const base::FeatureParam kIpPrivacyProxyBPsk; -// If true, use the `proxy_chains` provided by Phosphor. Otherwise, use the -// `first_hop_hostnames` (and thus always single-proxy chains). -NET_EXPORT extern const base::FeatureParam kIpPrivacyUseProxyChains; - // If true, pass OAuth token to Phosphor in GetProxyConfig API for IP // Protection. NET_EXPORT extern const base::FeatureParam @@ -440,6 +442,12 @@ NET_EXPORT extern const base::FeatureParam NET_EXPORT extern const base::FeatureParam kIpPrivacyAddHeaderToProxiedRequests; +// Token expirations will have a random time between 5 seconds and this delta +// subtracted from their expiration, in order to even out the load on the token +// servers. +NET_EXPORT extern const base::FeatureParam + kIpPrivacyExpirationFuzz; + // Whether QuicParams::migrate_sessions_on_network_change_v2 defaults to true or // false. This is needed as a workaround to set this value to true on Android // but not on WebView (until crbug.com/1430082 has been fixed). @@ -512,6 +520,9 @@ NET_EXPORT BASE_DECLARE_FEATURE(kUseNewAlpsCodepointQUIC); // while on stable channels. NET_EXPORT BASE_DECLARE_FEATURE(kTreatHTTPExpiresHeaderValueZeroAsExpired); +// Enables truncating the response body to the content length. +NET_EXPORT BASE_DECLARE_FEATURE(kTruncateBodyToContentLength); + } // namespace net::features #endif // NET_BASE_FEATURES_H_ diff --git a/naiveproxy/src/net/base/io_buffer.cc b/naiveproxy/src/net/base/io_buffer.cc index 889a6ca4b6..b62846f1f8 100644 --- a/naiveproxy/src/net/base/io_buffer.cc +++ b/naiveproxy/src/net/base/io_buffer.cc @@ -7,6 +7,7 @@ #include #include "base/check_op.h" +#include "base/containers/heap_array.h" #include "base/numerics/safe_math.h" namespace net { @@ -37,14 +38,14 @@ IOBufferWithSize::IOBufferWithSize() = default; IOBufferWithSize::IOBufferWithSize(size_t buffer_size) { AssertValidBufferSize(buffer_size); - if (buffer_size) { - size_ = buffer_size; - data_ = new char[buffer_size]; - } + storage_ = base::HeapArray::Uninit(buffer_size); + size_ = storage_.size(); + data_ = storage_.data(); } IOBufferWithSize::~IOBufferWithSize() { - data_.ClearAndDeleteArray(); + // Clear pointer before this destructor makes it dangle. + data_ = nullptr; } StringIOBuffer::StringIOBuffer(std::string s) : string_data_(std::move(s)) { diff --git a/naiveproxy/src/net/base/io_buffer.h b/naiveproxy/src/net/base/io_buffer.h index 24dfc5c3b9..5730942354 100644 --- a/naiveproxy/src/net/base/io_buffer.h +++ b/naiveproxy/src/net/base/io_buffer.h @@ -11,6 +11,7 @@ #include #include +#include "base/containers/heap_array.h" #include "base/containers/span.h" #include "base/memory/free_deleter.h" #include "base/memory/raw_ptr.h" @@ -121,6 +122,9 @@ class NET_EXPORT IOBufferWithSize : public IOBuffer { protected: ~IOBufferWithSize() override; + + private: + base::HeapArray storage_; }; // This is a read only IOBuffer. The data is stored in a string and diff --git a/naiveproxy/src/net/base/isolation_info.cc b/naiveproxy/src/net/base/isolation_info.cc index c58b63d3fc..17af935b7f 100644 --- a/naiveproxy/src/net/base/isolation_info.cc +++ b/naiveproxy/src/net/base/isolation_info.cc @@ -116,6 +116,13 @@ IsolationInfo IsolationInfo::CreateTransient() { SiteForCookies(), /*nonce=*/std::nullopt); } +IsolationInfo IsolationInfo::CreateTransientWithNonce( + const base::UnguessableToken& nonce) { + url::Origin opaque_origin; + return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin, + SiteForCookies(), nonce); +} + std::optional IsolationInfo::Deserialize( const std::string& serialized) { proto::IsolationInfo proto; diff --git a/naiveproxy/src/net/base/isolation_info.h b/naiveproxy/src/net/base/isolation_info.h index c391feb3da..d782f1b1ed 100644 --- a/naiveproxy/src/net/base/isolation_info.h +++ b/naiveproxy/src/net/base/isolation_info.h @@ -89,6 +89,13 @@ class NET_EXPORT IsolationInfo { // CreateForInternalRequest with a fresh opaque origin. static IsolationInfo CreateTransient(); + // Same as CreateTransient, with a `nonce` used to identify requests tagged + // with this IsolationInfo in the network service. The `nonce` provides no + // additional resource isolation, because the opaque origin in the resulting + // IsolationInfo already represents a unique partition. + static IsolationInfo CreateTransientWithNonce( + const base::UnguessableToken& nonce); + // Creates an IsolationInfo from the serialized contents. Returns a nullopt // if deserialization fails or if data is inconsistent. static std::optional Deserialize( diff --git a/naiveproxy/src/net/base/mac/url_conversions.h b/naiveproxy/src/net/base/mac/url_conversions.h deleted file mode 100644 index 520fbc7df5..0000000000 --- a/naiveproxy/src/net/base/mac/url_conversions.h +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_BASE_MAC_URL_CONVERSIONS_H_ -#define NET_BASE_MAC_URL_CONVERSIONS_H_ - -// TODO(crbug.com/1519486): Get rid of this header inclusion (and this entire -// file) as soon as we convert all of the usage from net/base/mac to -// net/base/apple. -#include "net/base/apple/url_conversions.h" - -#endif // NET_BASE_MAC_URL_CONVERSIONS_H_ diff --git a/naiveproxy/src/net/base/net_error_list.h b/naiveproxy/src/net/base/net_error_list.h index 8f188f5a0e..a3ef0f3a9a 100644 --- a/naiveproxy/src/net/base/net_error_list.h +++ b/naiveproxy/src/net/base/net_error_list.h @@ -820,6 +820,9 @@ NET_ERROR(CACHED_IP_ADDRESS_SPACE_BLOCKED_BY_PRIVATE_NETWORK_ACCESS_POLICY, // The connection is blocked by private network access checks. NET_ERROR(BLOCKED_BY_PRIVATE_NETWORK_ACCESS_CHECKS, -385) +// Content decoding failed due to the zstd window size being too big (over 8MB). +NET_ERROR(ZSTD_WINDOW_SIZE_TOO_BIG, -386) + // The cache does not have the requested entry. NET_ERROR(CACHE_MISS, -400) diff --git a/naiveproxy/src/net/base/net_string_util_icu.cc b/naiveproxy/src/net/base/net_string_util_icu.cc index 12c42befb8..c9dda73340 100644 --- a/naiveproxy/src/net/base/net_string_util_icu.cc +++ b/naiveproxy/src/net/base/net_string_util_icu.cc @@ -28,12 +28,11 @@ bool ConvertToUtf8(std::string_view text, // A single byte in a legacy encoding can be expanded to 3 bytes in UTF-8. // A 'two-byte character' in a legacy encoding can be expanded to 4 bytes - // in UTF-8. Therefore, the expansion ratio is 3 at most. Add one for a - // trailing '\0'. - size_t output_length = text.length() * 3 + 1; - char* buf = base::WriteInto(output, output_length); - output_length = ucnv_toAlgorithmic(UCNV_UTF8, converter, buf, output_length, - text.data(), text.length(), &err); + // in UTF-8. Therefore, the expansion ratio is 3 at most. + output->resize(text.length() * 3); + size_t output_length = + ucnv_toAlgorithmic(UCNV_UTF8, converter, output->data(), output->length(), + text.data(), text.length(), &err); ucnv_close(converter); if (U_FAILURE(err)) { output->clear(); diff --git a/naiveproxy/src/net/base/priority_queue.h b/naiveproxy/src/net/base/priority_queue.h index f69e512ba8..62544345b0 100644 --- a/naiveproxy/src/net/base/priority_queue.h +++ b/naiveproxy/src/net/base/priority_queue.h @@ -153,7 +153,7 @@ class PriorityQueue { unsigned id = next_id_; valid_ids_.insert(id); ++next_id_; - list.emplace_back(std::make_pair(id, std::move(value))); + list.emplace_back(id, std::move(value)); #else list.emplace_back(std::move(value)); #endif @@ -171,7 +171,7 @@ class PriorityQueue { unsigned id = next_id_; valid_ids_.insert(id); ++next_id_; - list.emplace_front(std::make_pair(id, std::move(value))); + list.emplace_front(std::pair(id, std::move(value))); #else list.emplace_front(std::move(value)); #endif diff --git a/naiveproxy/src/net/base/proxy_chain.cc b/naiveproxy/src/net/base/proxy_chain.cc index b0665536a5..1163913a4d 100644 --- a/naiveproxy/src/net/base/proxy_chain.cc +++ b/naiveproxy/src/net/base/proxy_chain.cc @@ -10,6 +10,7 @@ #include "base/check.h" #include "base/no_destructor.h" #include "base/ranges/algorithm.h" +#include "base/strings/stringprintf.h" #include "net/base/proxy_server.h" #include "net/base/proxy_string_util.h" @@ -23,18 +24,7 @@ ProxyChain::ProxyChain(const ProxyChain& other) = default; ProxyChain::ProxyChain(ProxyChain&& other) noexcept = default; ProxyChain& ProxyChain::operator=(const ProxyChain& other) = default; -// Note: We define this move assignment operator explicitly to make the -// `ForIpProtection()` method safer to use. Specifically, we want to prevent -// moving the `proxy_server_list_` in the event that self-assignment is -// occurring (i.e. "proxy_chain = std::move(proxy_chain).ForIpProtection()") or -// else the list of ProxyServers will get cleared. -ProxyChain& ProxyChain::operator=(ProxyChain&& other) noexcept { - if (this != &other) { - proxy_server_list_ = std::move(other.proxy_server_list_); - is_for_ip_protection_ = other.is_for_ip_protection_; - } - return *this; -} +ProxyChain& ProxyChain::operator=(ProxyChain&& other) noexcept = default; ProxyChain::~ProxyChain() = default; ProxyChain::ProxyChain(ProxyServer proxy_server) @@ -42,7 +32,7 @@ ProxyChain::ProxyChain(ProxyServer proxy_server) ProxyChain::ProxyChain(ProxyServer::Scheme scheme, const HostPortPair& host_port_pair) - : ProxyChain({ProxyServer(scheme, host_port_pair)}) {} + : ProxyChain(ProxyServer(scheme, host_port_pair)) {} ProxyChain::ProxyChain(std::vector proxy_server_list) : proxy_server_list_(std::move(proxy_server_list)) { @@ -66,23 +56,23 @@ std::pair ProxyChain::SplitLast() const { DCHECK(IsValid()); DCHECK_NE(length(), 0u); ProxyChain new_chain = - ProxyChain({proxy_server_list_->begin(), proxy_server_list_->end() - 1}); - new_chain.is_for_ip_protection_ = is_for_ip_protection_; + ProxyChain({proxy_server_list_->begin(), proxy_server_list_->end() - 1}, + ip_protection_chain_id_); return std::make_pair(new_chain, std::ref(proxy_server_list_->back())); } +const ProxyServer& ProxyChain::First() const { + DCHECK(IsValid()); + DCHECK_NE(length(), 0u); + return proxy_server_list_->front(); +} + const ProxyServer& ProxyChain::Last() const { DCHECK(IsValid()); DCHECK_NE(length(), 0u); return proxy_server_list_->back(); } -ProxyChain&& ProxyChain::ForIpProtection() && { - CHECK(IsValid()); - is_for_ip_protection_ = true; - return std::move(*this); -} - std::string ProxyChain::ToDebugString() const { if (!IsValid()) { return "INVALID PROXY CHAIN"; @@ -96,12 +86,22 @@ std::string ProxyChain::ToDebugString() const { debug_string += ProxyServerToProxyUri(proxy_server); } debug_string = "[" + debug_string + "]"; - if (is_for_ip_protection()) { + if (ip_protection_chain_id_ == 0) { debug_string += " (IP Protection)"; + } else if (ip_protection_chain_id_ >= 0) { + debug_string += base::StringPrintf(" (IP Protection chain %d)", + ip_protection_chain_id_); } return debug_string; } +ProxyChain::ProxyChain(std::vector proxy_server_list, + int ip_protection_chain_id) + : proxy_server_list_(std::move(proxy_server_list)), + ip_protection_chain_id_(ip_protection_chain_id) { + CHECK(IsValidInternal()); +} + bool ProxyChain::IsValidInternal() const { if (!proxy_server_list_.has_value()) { return false; @@ -109,10 +109,15 @@ bool ProxyChain::IsValidInternal() const { if (is_single_proxy()) { return proxy_server_list_.value().at(0).is_valid(); } - return base::ranges::all_of( + bool all_https = base::ranges::all_of( proxy_server_list_.value(), [](const auto& proxy_server) { return proxy_server.is_valid() && proxy_server.is_https(); }); + bool all_quic = base::ranges::all_of( + proxy_server_list_.value(), [](const auto& proxy_server) { + return proxy_server.is_valid() && proxy_server.is_quic(); + }); + return all_https || (all_quic && is_for_ip_protection()); } std::ostream& operator<<(std::ostream& os, const ProxyChain& proxy_chain) { diff --git a/naiveproxy/src/net/base/proxy_chain.h b/naiveproxy/src/net/base/proxy_chain.h index 42fcc2c288..e523937cbb 100644 --- a/naiveproxy/src/net/base/proxy_chain.h +++ b/naiveproxy/src/net/base/proxy_chain.h @@ -24,10 +24,6 @@ namespace net { // servers means that a single connection will go through all of the proxies in // order, using a tunnel through the first proxy to connect to the second, etc. // A "direct" connection is a chain of length zero. -// -// TODO(crbug.com/1491092): Initial implementations of proxy chaining may, in -// fact, not tunnel through the last proxy in the ProxyChain if the destination -// is http. class NET_EXPORT ProxyChain { public: // Constructs an invalid ProxyChain. @@ -70,6 +66,14 @@ class NET_EXPORT ProxyChain { // Create a "direct" proxy chain, which includes no proxy servers. static ProxyChain Direct() { return ProxyChain(std::vector()); } + // Creates a `ProxyChain` for use by the IP Protection feature. This is used + // for metrics collection and for special handling. If not give, the + // chain_id defaults to 0 which corresponds to an un-identified chain. + static ProxyChain ForIpProtection(std::vector proxy_server_list, + int chain_id = 0) { + return ProxyChain(std::move(proxy_server_list), chain_id); + } + // Get ProxyServer at index in chain. This is not valid for direct or invalid // proxy chains. const ProxyServer& GetProxyServer(size_t chain_index) const; @@ -83,6 +87,10 @@ class NET_EXPORT ProxyChain { // only has one proxy server, then the resulting chain will be direct. std::pair SplitLast() const; + // Get the first ProxyServer in this chain, which must have at least one + // server. + const ProxyServer& First() const; + // Get the last ProxyServer in this chain, which must have at least one // server. const ProxyServer& Last() const; @@ -123,42 +131,58 @@ class NET_EXPORT ProxyChain { // instead of establishing a tunnel with CONNECT. This is currently not // supported for multi-proxy chains. bool is_get_to_proxy_allowed() const { - return is_single_proxy() && GetProxyServer(0).is_http_like(); + return is_single_proxy() && First().is_http_like(); } // Returns true if a proxy server list is available. bool IsValid() const { return proxy_server_list_.has_value(); } - // Returns a `ProxyChain` for use by the IP Protection feature. This is used - // for metrics collection and for special handling (for instance, IP - // protection proxy chains will have an authorization header appended to the - // CONNECT requests sent to the proxy servers, and requests sent through an - // IP Protection proxy chain will have an "IP-Protection: 1" header added to - // them). - ProxyChain&& ForIpProtection() &&; - bool is_for_ip_protection() const { return is_for_ip_protection_; } + // A negative value for `ip_protection_chain_id()` indicating this is not an + // IP protection chain. All IP-Protection chain IDs are non-negative. + static constexpr int kNotIpProtectionChainId = -1; + + // A value for `ip_protection_chain_id()` for IP protection chains for which + // no other chain ID was specified. + static constexpr int kDefaultIpProtectionChainId = 0; + + // The largest allowed ip_protection_chain_id. + static constexpr int kMaxIpProtectionChainId = 3; + + bool is_for_ip_protection() const { + return ip_protection_chain_id_ != kNotIpProtectionChainId; + } + int ip_protection_chain_id() const { return ip_protection_chain_id_; } bool operator==(const ProxyChain& other) const { - return std::tie(proxy_server_list_, is_for_ip_protection_) == - std::tie(other.proxy_server_list_, other.is_for_ip_protection_); + return std::tie(proxy_server_list_, ip_protection_chain_id_) == + std::tie(other.proxy_server_list_, other.ip_protection_chain_id_); } bool operator!=(const ProxyChain& other) const { return !(*this == other); } // Comparator function so this can be placed in a std::map. bool operator<(const ProxyChain& other) const { - return std::tie(proxy_server_list_, is_for_ip_protection_) < - std::tie(other.proxy_server_list_, other.is_for_ip_protection_); + return std::tie(proxy_server_list_, ip_protection_chain_id_) < + std::tie(other.proxy_server_list_, other.ip_protection_chain_id_); } std::string ToDebugString() const; private: + explicit ProxyChain(std::vector proxy_server_list, + int ip_protection_chain_id); + std::optional> proxy_server_list_; - bool is_for_ip_protection_ = false; + // If used for IP protection, this is the chain_id received from the server. + // A negative value indicates this chain is not used for IP protection. + int ip_protection_chain_id_ = kNotIpProtectionChainId; - // Returns true if this chain is valid. + // Returns true if this chain is valid. A chain is considered valid if (1) is + // a single valid proxy server. If single QUIC proxy, it must + // also be an IP protection proxy chain. (2) is multi-proxy and + // all servers are either HTTPS or QUIC. If QUIC servers, it must also + // be an IP protection proxy chain. bool IsValidInternal() const; }; diff --git a/naiveproxy/src/net/base/session_usage.h b/naiveproxy/src/net/base/session_usage.h new file mode 100644 index 0000000000..e675c6a9dc --- /dev/null +++ b/naiveproxy/src/net/base/session_usage.h @@ -0,0 +1,37 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_BASE_SESSION_USAGE_H_ +#define NET_BASE_SESSION_USAGE_H_ + +namespace net { + +// This type distinguishes sessions carrying traffic through the destination +// host from sessions carrying traffic directly to the host. Credentials such +// as cookies are attached to `kDestination` sessions, but not to `kProxy` +// sessions. This type is used in QUIC and SPDY session keys, together with a +// proxy chain and host-port pair, to prevent pooling such sessions together. +// +// Examples: +// +// A session with no proxies at all will have a direct proxy chain and +// `session_usage = kDestination`. +// +// A session to "dest" carried over one or more proxies will have those +// proxies in its proxy chain, "dest" in its host-port pair, and `session_usage +// = kDestination`. +// +// A session over "proxyA" to "proxyB" which is carrying tunneled traffic to +// "dest" will have "proxyA" in its proxy chain, "proxyB in +// its host-port pair, and `session_usage = kProxy`. +enum class SessionUsage { + // This session is used for a connection to the destination host. + kDestination, + // This session is used to proxy traffic to other destinations. + kProxy, +}; + +} // namespace net + +#endif // NET_BASE_SESSION_USAGE_H_ diff --git a/naiveproxy/src/net/base/url_util.cc b/naiveproxy/src/net/base/url_util.cc index 81e7c3fa15..75b0fb96c0 100644 --- a/naiveproxy/src/net/base/url_util.cc +++ b/naiveproxy/src/net/base/url_util.cc @@ -96,8 +96,7 @@ GURL AppendOrReplaceQueryParameter(const GURL& url, url::Component cursor(0, input.size()); std::string output; url::Component key_range, value_range; - while (url::ExtractQueryKeyValue(input.data(), &cursor, &key_range, - &value_range)) { + while (url::ExtractQueryKeyValue(input, &cursor, &key_range, &value_range)) { const std::string_view key = input.substr(key_range.begin, key_range.len); std::string key_value_pair; // Check |replaced| as only the first pair should be replaced. @@ -178,8 +177,7 @@ void QueryIterator::Advance() { key_.reset(); value_.reset(); unescaped_value_.clear(); - at_end_ = - !url::ExtractQueryKeyValue(url_->spec().c_str(), &query_, &key_, &value_); + at_end_ = !url::ExtractQueryKeyValue(url_->spec(), &query_, &key_, &value_); } bool GetValueForKeyInQuery(const GURL& url, diff --git a/naiveproxy/src/net/cert/asn1_util.cc b/naiveproxy/src/net/cert/asn1_util.cc index 26de465d23..6e27c49d66 100644 --- a/naiveproxy/src/net/cert/asn1_util.cc +++ b/naiveproxy/src/net/cert/asn1_util.cc @@ -4,9 +4,9 @@ #include "net/cert/asn1_util.h" +#include #include -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/input.h" #include "third_party/boringssl/src/pki/parse_certificate.h" #include "third_party/boringssl/src/pki/parser.h" @@ -50,25 +50,24 @@ bool SeekToSubject(bssl::der::Input in, bssl::der::Parser* tbs_certificate) { bool unused; if (!tbs_certificate->SkipOptionalTag( - bssl::der::kTagConstructed | bssl::der::kTagContextSpecific | 0, - &unused)) { + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0, &unused)) { return false; } // serialNumber - if (!tbs_certificate->SkipTag(bssl::der::kInteger)) { + if (!tbs_certificate->SkipTag(CBS_ASN1_INTEGER)) { return false; } // signature - if (!tbs_certificate->SkipTag(bssl::der::kSequence)) { + if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) { return false; } // issuer - if (!tbs_certificate->SkipTag(bssl::der::kSequence)) { + if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) { return false; } // validity - if (!tbs_certificate->SkipTag(bssl::der::kSequence)) { + if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) { return false; } return true; @@ -81,7 +80,7 @@ bool SeekToSubject(bssl::der::Input in, bssl::der::Parser* tbs_certificate) { bool SeekToSPKI(bssl::der::Input in, bssl::der::Parser* tbs_certificate) { return SeekToSubject(in, tbs_certificate) && // Skip over Subject. - tbs_certificate->SkipTag(bssl::der::kSequence); + tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE); } // Parses input |in| which should point to the beginning of a @@ -109,24 +108,23 @@ bool SeekToExtensions(bssl::der::Input in, // extensions [3] EXPLICIT Extensions OPTIONAL } // subjectPublicKeyInfo - if (!tbs_cert_parser.SkipTag(bssl::der::kSequence)) { + if (!tbs_cert_parser.SkipTag(CBS_ASN1_SEQUENCE)) { return false; } // issuerUniqueID - if (!tbs_cert_parser.SkipOptionalTag(bssl::der::kTagContextSpecific | 1, + if (!tbs_cert_parser.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1, &present)) { return false; } // subjectUniqueID - if (!tbs_cert_parser.SkipOptionalTag(bssl::der::kTagContextSpecific | 2, + if (!tbs_cert_parser.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2, &present)) { return false; } - absl::optional extensions; + std::optional extensions; if (!tbs_cert_parser.ReadOptionalTag( - bssl::der::kTagConstructed | bssl::der::kTagContextSpecific | 3, - &extensions)) { + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3, &extensions)) { return false; } @@ -236,13 +234,13 @@ bool ExtractSubjectPublicKeyFromSPKI(std::string_view spki, return false; // Step over algorithm field (a SEQUENCE). - if (!spki_parser.SkipTag(bssl::der::kSequence)) { + if (!spki_parser.SkipTag(CBS_ASN1_SEQUENCE)) { return false; } // Extract the subjectPublicKey field. bssl::der::Input spk; - if (!spki_parser.ReadTag(bssl::der::kBitString, &spk)) { + if (!spki_parser.ReadTag(CBS_ASN1_BITSTRING, &spk)) { return false; } *spk_out = spk.AsStringView(); @@ -301,13 +299,12 @@ bool ExtractSignatureAlgorithmsFromDERCert( bool unused; if (!tbs_certificate.SkipOptionalTag( - bssl::der::kTagConstructed | bssl::der::kTagContextSpecific | 0, - &unused)) { + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0, &unused)) { return false; } // serialNumber - if (!tbs_certificate.SkipTag(bssl::der::kInteger)) { + if (!tbs_certificate.SkipTag(CBS_ASN1_INTEGER)) { return false; } // signature diff --git a/naiveproxy/src/net/cert/cert_status_flags.cc b/naiveproxy/src/net/cert/cert_status_flags.cc index 278c48ad3e..700a78bfef 100644 --- a/naiveproxy/src/net/cert/cert_status_flags.cc +++ b/naiveproxy/src/net/cert/cert_status_flags.cc @@ -10,51 +10,6 @@ namespace net { -CertStatus MapNetErrorToCertStatus(int error) { - switch (error) { - case ERR_CERT_COMMON_NAME_INVALID: - return CERT_STATUS_COMMON_NAME_INVALID; - case ERR_CERT_DATE_INVALID: - return CERT_STATUS_DATE_INVALID; - case ERR_CERT_AUTHORITY_INVALID: - return CERT_STATUS_AUTHORITY_INVALID; - case ERR_CERT_NO_REVOCATION_MECHANISM: - return CERT_STATUS_NO_REVOCATION_MECHANISM; - case ERR_CERT_UNABLE_TO_CHECK_REVOCATION: - return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; - case ERR_CERTIFICATE_TRANSPARENCY_REQUIRED: - return CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED; - case ERR_CERT_REVOKED: - return CERT_STATUS_REVOKED; - // We added the ERR_CERT_CONTAINS_ERRORS error code when we were using - // WinInet, but we never figured out how it differs from ERR_CERT_INVALID. - // We should not use ERR_CERT_CONTAINS_ERRORS in new code. - case ERR_CERT_CONTAINS_ERRORS: - NOTREACHED(); - [[fallthrough]]; - case ERR_CERT_INVALID: - return CERT_STATUS_INVALID; - case ERR_CERT_WEAK_SIGNATURE_ALGORITHM: - return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM; - case ERR_CERT_NON_UNIQUE_NAME: - return CERT_STATUS_NON_UNIQUE_NAME; - case ERR_CERT_WEAK_KEY: - return CERT_STATUS_WEAK_KEY; - case ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: - return CERT_STATUS_PINNED_KEY_MISSING; - case ERR_CERT_NAME_CONSTRAINT_VIOLATION: - return CERT_STATUS_NAME_CONSTRAINT_VIOLATION; - case ERR_CERT_VALIDITY_TOO_LONG: - return CERT_STATUS_VALIDITY_TOO_LONG; - case ERR_CERT_SYMANTEC_LEGACY: - return CERT_STATUS_SYMANTEC_LEGACY; - case ERR_CERT_KNOWN_INTERCEPTION_BLOCKED: - return (CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED | CERT_STATUS_REVOKED); - default: - return 0; - } -} - int MapCertStatusToNetError(CertStatus cert_status) { // A certificate may have multiple errors. We report the most // serious error. diff --git a/naiveproxy/src/net/cert/cert_status_flags.h b/naiveproxy/src/net/cert/cert_status_flags.h index 20e648a81c..61b42853bf 100644 --- a/naiveproxy/src/net/cert/cert_status_flags.h +++ b/naiveproxy/src/net/cert/cert_status_flags.h @@ -30,15 +30,6 @@ inline bool IsCertStatusError(CertStatus status) { return (CERT_STATUS_ALL_ERRORS & status) != 0; } -// Maps a network error code to the equivalent certificate status flag. If -// the error code is not a certificate error, it is mapped to 0. -// Note: It is not safe to go net::CertStatus -> net::Error -> net::CertStatus, -// as the CertStatus contains more information. Conversely, going from -// net::Error -> net::CertStatus -> net::Error is not a lossy function, for the -// same reason. -// To avoid incorrect use, this is only exported for unittest helpers. -NET_EXPORT_PRIVATE CertStatus MapNetErrorToCertStatus(int error); - // Maps the most serious certificate error in the certificate status flags // to the equivalent network error code. NET_EXPORT int MapCertStatusToNetError(CertStatus cert_status); diff --git a/naiveproxy/src/net/cert/cert_verifier.cc b/naiveproxy/src/net/cert/cert_verifier.cc index d3e6924fa2..f3c0959e5d 100644 --- a/naiveproxy/src/net/cert/cert_verifier.cc +++ b/naiveproxy/src/net/cert/cert_verifier.cc @@ -8,7 +8,7 @@ #include #include -#include "base/strings/string_util.h" +#include "base/containers/span.h" #include "base/types/optional_util.h" #include "build/build_config.h" #include "net/base/features.h" @@ -62,6 +62,17 @@ class DefaultCertVerifyProcFactory : public net::CertVerifyProcFactory { ~DefaultCertVerifyProcFactory() override = default; }; +base::span CryptoBufferToSpan(const CRYPTO_BUFFER* b) { + return base::make_span(CRYPTO_BUFFER_data(b), CRYPTO_BUFFER_len(b)); +} + +void Sha256UpdateLengthPrefixed(SHA256_CTX* ctx, base::span s) { + // Include a length prefix to ensure the hash is injective. + uint64_t l = s.size(); + SHA256_Update(ctx, reinterpret_cast(&l), sizeof(l)); + SHA256_Update(ctx, s.data(), s.size()); +} + } // namespace CertVerifier::Config::Config() = default; @@ -90,19 +101,17 @@ CertVerifier::RequestParams::RequestParams( // sake. SHA256_CTX ctx; SHA256_Init(&ctx); - SHA256_Update(&ctx, CRYPTO_BUFFER_data(certificate_->cert_buffer()), - CRYPTO_BUFFER_len(certificate_->cert_buffer())); + Sha256UpdateLengthPrefixed(&ctx, + CryptoBufferToSpan(certificate_->cert_buffer())); for (const auto& cert_handle : certificate_->intermediate_buffers()) { - SHA256_Update(&ctx, CRYPTO_BUFFER_data(cert_handle.get()), - CRYPTO_BUFFER_len(cert_handle.get())); + Sha256UpdateLengthPrefixed(&ctx, CryptoBufferToSpan(cert_handle.get())); } - SHA256_Update(&ctx, hostname.data(), hostname.size()); + Sha256UpdateLengthPrefixed(&ctx, base::as_byte_span(hostname)); SHA256_Update(&ctx, &flags, sizeof(flags)); - SHA256_Update(&ctx, ocsp_response.data(), ocsp_response.size()); - SHA256_Update(&ctx, sct_list.data(), sct_list.size()); - SHA256_Final(reinterpret_cast( - base::WriteInto(&key_, SHA256_DIGEST_LENGTH + 1)), - &ctx); + Sha256UpdateLengthPrefixed(&ctx, base::as_byte_span(ocsp_response)); + Sha256UpdateLengthPrefixed(&ctx, base::as_byte_span(sct_list)); + key_.resize(SHA256_DIGEST_LENGTH); + SHA256_Final(reinterpret_cast(key_.data()), &ctx); } CertVerifier::RequestParams::RequestParams(const RequestParams& other) = diff --git a/naiveproxy/src/net/cert/cert_verify_proc.cc b/naiveproxy/src/net/cert/cert_verify_proc.cc index 2973634605..0e6fc76f7c 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include "base/containers/flat_set.h" @@ -285,9 +286,9 @@ void RecordTrustAnchorHistogram(const HashValueVector& spki_hashes, return false; } - absl::optional cert_algorithm = + std::optional cert_algorithm = bssl::ParseSignatureAlgorithm(bssl::der::Input(cert_algorithm_sequence)); - absl::optional tbs_algorithm = + std::optional tbs_algorithm = bssl::ParseSignatureAlgorithm(bssl::der::Input(tbs_algorithm_sequence)); if (!cert_algorithm || !tbs_algorithm || *cert_algorithm != *tbs_algorithm) { return false; @@ -459,7 +460,8 @@ int CertVerifyProc::Verify(X509Certificate* cert, const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log) { + const NetLogWithSource& net_log, + std::optional time_now) { CHECK(cert); CHECK(verify_result); @@ -480,7 +482,7 @@ int CertVerifyProc::Verify(X509Certificate* cert, verify_result->verified_cert = cert; int rv = VerifyInternal(cert, hostname, ocsp_response, sct_list, flags, - verify_result, net_log); + verify_result, net_log, time_now); CHECK(verify_result->verified_cert); diff --git a/naiveproxy/src/net/cert/cert_verify_proc.h b/naiveproxy/src/net/cert/cert_verify_proc.h index 7beed622f4..e7b62679ec 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc.h +++ b/naiveproxy/src/net/cert/cert_verify_proc.h @@ -92,7 +92,7 @@ class NET_EXPORT CertVerifyProc std::vector> ct_logs; scoped_refptr ct_policy_enforcer; #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) - absl::optional root_store_data; + std::optional root_store_data; #endif #if BUILDFLAG(CHROME_ROOT_STORE_OPTIONAL) bool use_chrome_root_store; @@ -196,6 +196,9 @@ class NET_EXPORT CertVerifyProc // // |flags| is bitwise OR'd of VerifyFlags: // + // If |time_now| is set it will be used as the current time, otherwise the + // system time will be used. + // // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, online certificate // revocation checking is performed (i.e. OCSP and downloading CRLs). CRLSet // based revocation checking is always enabled, regardless of this flag. @@ -205,7 +208,8 @@ class NET_EXPORT CertVerifyProc const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log); + const NetLogWithSource& net_log, + std::optional time_now = std::nullopt); protected: explicit CertVerifyProc(scoped_refptr crl_set); @@ -246,6 +250,11 @@ class NET_EXPORT CertVerifyProc // |verify_result->cert_status| should be non-zero, indicating an // error occurred. // + // If |time_now| is not nullopt, it will be used as the current time for + // certificate verification, if it is nullopt, the system time will be used + // instead. If a certificate verification fails with a NotBefore/NotAfter + // error when |time_now| is set, it will be retried with the system time. + // // On success, net::OK should be returned, with |verify_result| updated to // reflect the successfully verified chain. virtual int VerifyInternal(X509Certificate* cert, @@ -254,7 +263,8 @@ class NET_EXPORT CertVerifyProc const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log) = 0; + const NetLogWithSource& net_log, + std::optional time_now) = 0; // HasNameConstraintsViolation returns true iff one of |public_key_hashes| // (which are hashes of SubjectPublicKeyInfo structures) has name constraints diff --git a/naiveproxy/src/net/cert/cert_verify_proc_android.cc b/naiveproxy/src/net/cert/cert_verify_proc_android.cc index 9420f07140..079d9f12ea 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_android.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_android.cc @@ -352,14 +352,14 @@ CertVerifyProcAndroid::CertVerifyProcAndroid( CertVerifyProcAndroid::~CertVerifyProcAndroid() = default; -int CertVerifyProcAndroid::VerifyInternal( - X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - const std::string& sct_list, - int flags, - CertVerifyResult* verify_result, - const NetLogWithSource& net_log) { +int CertVerifyProcAndroid::VerifyInternal(X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + const std::string& sct_list, + int flags, + CertVerifyResult* verify_result, + const NetLogWithSource& net_log, + std::optional) { std::vector cert_bytes; GetChainDEREncodedBytes(cert, &cert_bytes); if (!VerifyFromAndroidTrustManager(cert_bytes, hostname, flags, diff --git a/naiveproxy/src/net/cert/cert_verify_proc_android.h b/naiveproxy/src/net/cert/cert_verify_proc_android.h index f874bff264..ea336cbeaa 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_android.h +++ b/naiveproxy/src/net/cert/cert_verify_proc_android.h @@ -32,7 +32,8 @@ class NET_EXPORT CertVerifyProcAndroid : public CertVerifyProc { const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log) override; + const NetLogWithSource& net_log, + std::optional) override; scoped_refptr cert_net_fetcher_; }; diff --git a/naiveproxy/src/net/cert/cert_verify_proc_blocklist.inc b/naiveproxy/src/net/cert/cert_verify_proc_blocklist.inc index f6a55dac91..c7808b3951 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_blocklist.inc +++ b/naiveproxy/src/net/cert/cert_verify_proc_blocklist.inc @@ -391,6 +391,10 @@ static constexpr uint8_t {0x02, 0xa9, 0x5f, 0x43, 0x43, 0x10, 0x19, 0xe9, 0xdc, 0x22, 0x5f, 0x05, 0xf4, 0x19, 0x33, 0x01, 0x90, 0xde, 0xb4, 0xa3, 0xf1, 0x86, 0x9c, 0xaa, 0xc9, 0x84, 0x2b, 0x40, 0x3d, 0xcb, 0xee, 0x77}, + // 89107c8e50e029b7b5f4ff0ccd2956bcc9d0c8ba2bfb6a58374ed63a6b034a30.pem + {0x89, 0x28, 0xc5, 0x93, 0x98, 0xb0, 0xf1, 0x71, 0xc0, 0xf9, 0x6f, + 0xda, 0xe6, 0xab, 0x8d, 0xd0, 0xf4, 0x8e, 0xe0, 0x6d, 0x17, 0x4d, + 0xa1, 0x0c, 0x40, 0x4a, 0xc0, 0x01, 0x43, 0xc7, 0xa7, 0x49}, }; // Hashes of SubjectPublicKeyInfos known to be used for interception by a @@ -432,4 +436,8 @@ static constexpr uint8_t kKnownInterceptionList[][crypto::kSHA256Length] = { {0x02, 0xa9, 0x5f, 0x43, 0x43, 0x10, 0x19, 0xe9, 0xdc, 0x22, 0x5f, 0x05, 0xf4, 0x19, 0x33, 0x01, 0x90, 0xde, 0xb4, 0xa3, 0xf1, 0x86, 0x9c, 0xaa, 0xc9, 0x84, 0x2b, 0x40, 0x3d, 0xcb, 0xee, 0x77}, + // 89107c8e50e029b7b5f4ff0ccd2956bcc9d0c8ba2bfb6a58374ed63a6b034a30.pem + {0x89, 0x28, 0xc5, 0x93, 0x98, 0xb0, 0xf1, 0x71, 0xc0, 0xf9, 0x6f, + 0xda, 0xe6, 0xab, 0x8d, 0xd0, 0xf4, 0x8e, 0xe0, 0x6d, 0x17, 0x4d, + 0xa1, 0x0c, 0x40, 0x4a, 0xc0, 0x01, 0x43, 0xc7, 0xa7, 0x49}, }; diff --git a/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc b/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc index ba9185e9c1..d5528ef1ff 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_builtin.cc @@ -5,6 +5,7 @@ #include "net/cert/cert_verify_proc_builtin.h" #include +#include #include #include #include @@ -35,7 +36,6 @@ #include "net/cert/x509_util.h" #include "net/log/net_log_values.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/cert_errors.h" #include "third_party/boringssl/src/pki/cert_issuer_source_static.h" #include "third_party/boringssl/src/pki/common_cert_errors.h" @@ -202,8 +202,7 @@ class CertVerifyProcTrustStore { bool IsKnownRoot(const bssl::ParsedCertificate* trust_anchor) const { if (TestRootCerts::HasInstance() && - TestRootCerts::GetInstance()->IsKnownRoot( - trust_anchor->der_cert().AsSpan())) { + TestRootCerts::GetInstance()->IsKnownRoot(trust_anchor->der_cert())) { return true; } return system_trust_store_->IsKnownRoot(trust_anchor); @@ -505,7 +504,8 @@ class CertVerifyProcBuiltin : public CertVerifyProc { const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log) override; + const NetLogWithSource& net_log, + std::optional time_now) override; const scoped_refptr net_fetcher_; const std::unique_ptr ct_verifier_; @@ -723,16 +723,20 @@ scoped_refptr CreateVerifiedCertChain( // certificates. struct BuildPathAttempt { BuildPathAttempt(VerificationType verification_type, - bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy) - : verification_type(verification_type), digest_policy(digest_policy) {} + bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy, + bool use_system_time) + : verification_type(verification_type), + digest_policy(digest_policy), + use_system_time(use_system_time) {} - explicit BuildPathAttempt(VerificationType verification_type) - : BuildPathAttempt( - verification_type, - bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong) {} + BuildPathAttempt(VerificationType verification_type, bool use_system_time) + : BuildPathAttempt(verification_type, + bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong, + use_system_time) {} VerificationType verification_type; bssl::SimplePathBuilderDelegate::DigestPolicy digest_policy; + bool use_system_time; }; bssl::CertPathBuilder::Result TryBuildPath( @@ -769,7 +773,7 @@ bssl::CertPathBuilder::Result TryBuildPath( digest_policy, flags, trust_store, ocsp_response, sct_list, ev_metadata, checked_revocation, deadline, net_log); - absl::optional aia_cert_issuer_source; + std::optional aia_cert_issuer_source; // Initialize the path builder. bssl::CertPathBuilder path_builder( @@ -900,25 +904,41 @@ bool CanTryAgainWithWeakerDigestPolicy( bssl::cert_errors::kUnacceptableSignatureAlgorithm); } -int CertVerifyProcBuiltin::VerifyInternal( - X509Certificate* input_cert, - const std::string& hostname, - const std::string& ocsp_response, - const std::string& sct_list, - int flags, - CertVerifyResult* verify_result, - const NetLogWithSource& net_log) { - // VerifyInternal() is expected to carry out verifications using the current - // time stamp. - base::Time verification_time = base::Time::Now(); +// Returns true if retrying with the system time as the verification time might +// successfully build a path, based on the earlier failed |result|. +bool CanTryAgainWithSystemTime(const bssl::CertPathBuilder::Result& result) { + return result.AnyPathContainsError( + bssl::cert_errors::kValidityFailedNotAfter) || + result.AnyPathContainsError( + bssl::cert_errors::kValidityFailedNotBefore); +} + +int CertVerifyProcBuiltin::VerifyInternal(X509Certificate* input_cert, + const std::string& hostname, + const std::string& ocsp_response, + const std::string& sct_list, + int flags, + CertVerifyResult* verify_result, + const NetLogWithSource& net_log, + std::optional time_now) { base::TimeTicks deadline = base::TimeTicks::Now() + kMaxVerificationTime; - bssl::der::GeneralizedTime der_verification_time; - if (!EncodeTimeAsGeneralizedTime(verification_time, &der_verification_time)) { + bssl::der::GeneralizedTime der_verification_system_time; + bssl::der::GeneralizedTime der_verification_custom_time; + if (!EncodeTimeAsGeneralizedTime(base::Time::Now(), + &der_verification_system_time)) { // This shouldn't be possible. // We don't really have a good error code for this type of error. verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; return ERR_CERT_AUTHORITY_INVALID; } + if (time_now.has_value()) { + if (!EncodeTimeAsGeneralizedTime(time_now.value(), + &der_verification_custom_time)) { + // This shouldn't be possible, but if it somehow happens, just use system + // time. + der_verification_custom_time = der_verification_system_time; + } + } #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) int64_t chrome_root_store_version = system_trust_store_->chrome_root_store_version(); @@ -976,10 +996,10 @@ int CertVerifyProcBuiltin::VerifyInternal( // First try EV validation. Can skip this if the leaf certificate has no // chance of verifying as EV (lacks an EV policy). if (IsEVCandidate(ev_metadata, target.get())) - attempts.emplace_back(VerificationType::kEV); + attempts.emplace_back(VerificationType::kEV, !time_now.has_value()); // Next try DV validation. - attempts.emplace_back(VerificationType::kDV); + attempts.emplace_back(VerificationType::kDV, !time_now.has_value()); bssl::CertPathBuilder::Result result; VerificationType verification_type = VerificationType::kDV; @@ -1008,9 +1028,11 @@ int CertVerifyProcBuiltin::VerifyInternal( // Run the attempt through the path builder. result = TryBuildPath( - target, &intermediates, &trust_store, der_verification_time, deadline, - cur_attempt.verification_type, cur_attempt.digest_policy, flags, - ocsp_response, sct_list, crl_set(), ct_verifier_.get(), + target, &intermediates, &trust_store, + cur_attempt.use_system_time ? der_verification_system_time + : der_verification_custom_time, + deadline, cur_attempt.verification_type, cur_attempt.digest_policy, + flags, ocsp_response, sct_list, crl_set(), ct_verifier_.get(), ct_policy_enforcer_.get(), net_fetcher_.get(), ev_metadata, &checked_revocation_for_some_path, net_log); @@ -1028,19 +1050,24 @@ int CertVerifyProcBuiltin::VerifyInternal( break; } - // If this path building attempt (may have) failed due to the chain using a - // weak signature algorithm, enqueue a similar attempt but with weaker - // signature algorithms (SHA1) permitted. - // - // This fallback is necessary because the CertVerifyProc layer may decide to - // allow SHA1 based on its own policy, so path building should return - // possibly weak chains too. - // - // TODO(eroman): Would be better for the SHA1 policy to be part of the - // delegate instead so it can interact with path building. - if (cur_attempt.digest_policy == - bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong && - CanTryAgainWithWeakerDigestPolicy(result)) { + if (!cur_attempt.use_system_time && CanTryAgainWithSystemTime(result)) { + BuildPathAttempt system_time_attempt = cur_attempt; + system_time_attempt.use_system_time = true; + attempts.push_back(system_time_attempt); + } else if (cur_attempt.digest_policy == + bssl::SimplePathBuilderDelegate::DigestPolicy::kStrong && + CanTryAgainWithWeakerDigestPolicy(result)) { + // If this path building attempt (may have) failed due to the chain using + // a + // weak signature algorithm, enqueue a similar attempt but with weaker + // signature algorithms (SHA1) permitted. + // + // This fallback is necessary because the CertVerifyProc layer may decide + // to allow SHA1 based on its own policy, so path building should return + // possibly weak chains too. + // + // TODO(eroman): Would be better for the SHA1 policy to be part of the + // delegate instead so it can interact with path building. BuildPathAttempt sha1_fallback_attempt = cur_attempt; sha1_fallback_attempt.digest_policy = bssl::SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1; diff --git a/naiveproxy/src/net/cert/cert_verify_proc_ios.cc b/naiveproxy/src/net/cert/cert_verify_proc_ios.cc index e7884887ec..fb7d637c2c 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_ios.cc +++ b/naiveproxy/src/net/cert/cert_verify_proc_ios.cc @@ -390,14 +390,14 @@ CertStatus CertVerifyProcIOS::GetCertFailureStatusFromTrust(SecTrustRef trust) { CertVerifyProcIOS::~CertVerifyProcIOS() = default; -int CertVerifyProcIOS::VerifyInternal( - X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - const std::string& sct_list, - int flags, - CertVerifyResult* verify_result, - const NetLogWithSource& net_log) { +int CertVerifyProcIOS::VerifyInternal(X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + const std::string& sct_list, + int flags, + CertVerifyResult* verify_result, + const NetLogWithSource& net_log, + std::optional time_now) { ScopedCFTypeRef trust_policies; OSStatus status = CreateTrustPolicies(&trust_policies); if (status) diff --git a/naiveproxy/src/net/cert/cert_verify_proc_ios.h b/naiveproxy/src/net/cert/cert_verify_proc_ios.h index a5a53085a9..d10474d3ae 100644 --- a/naiveproxy/src/net/cert/cert_verify_proc_ios.h +++ b/naiveproxy/src/net/cert/cert_verify_proc_ios.h @@ -43,7 +43,8 @@ class CertVerifyProcIOS : public CertVerifyProc { const std::string& sct_list, int flags, CertVerifyResult* verify_result, - const NetLogWithSource& net_log) override; + const NetLogWithSource& net_log, + std::optional time_now) override; }; } // namespace net diff --git a/naiveproxy/src/net/cert/crl_set.cc b/naiveproxy/src/net/cert/crl_set.cc index e0c1e470c5..879477fa8a 100644 --- a/naiveproxy/src/net/cert/crl_set.cc +++ b/naiveproxy/src/net/cert/crl_set.cc @@ -54,26 +54,26 @@ namespace { // ReadHeader reads the header (including length prefix) from |data| and // updates |data| to remove the header on return. Caller takes ownership of the // returned pointer. -absl::optional ReadHeader(std::string_view* data) { +std::optional ReadHeader(std::string_view* data) { uint16_t header_len; if (data->size() < sizeof(header_len)) { - return absl::nullopt; + return std::nullopt; } // Assumes little-endian. memcpy(&header_len, data->data(), sizeof(header_len)); data->remove_prefix(sizeof(header_len)); if (data->size() < header_len) { - return absl::nullopt; + return std::nullopt; } const std::string_view header_bytes = data->substr(0, header_len); data->remove_prefix(header_len); - absl::optional header = + std::optional header = base::JSONReader::Read(header_bytes, base::JSON_ALLOW_TRAILING_COMMAS); if (!header || !header->is_dict()) { - return absl::nullopt; + return std::nullopt; } return header; @@ -215,7 +215,7 @@ bool CRLSet::Parse(std::string_view data, scoped_refptr* out_crl_set) { #error assumes little endian #endif - absl::optional header_value = ReadHeader(&data); + std::optional header_value = ReadHeader(&data); if (!header_value) { return false; } @@ -229,7 +229,7 @@ bool CRLSet::Parse(std::string_view data, scoped_refptr* out_crl_set) { if (header_dict.FindInt("Version") != kCurrentFileVersion) return false; - absl::optional sequence = header_dict.FindInt("Sequence"); + std::optional sequence = header_dict.FindInt("Sequence"); if (!sequence) return false; diff --git a/naiveproxy/src/net/cert/ct_log_verifier_util.cc b/naiveproxy/src/net/cert/ct_log_verifier_util.cc index ea67bb3c5b..d7230ef9ee 100644 --- a/naiveproxy/src/net/cert/ct_log_verifier_util.cc +++ b/naiveproxy/src/net/cert/ct_log_verifier_util.cc @@ -20,9 +20,8 @@ std::string HashNodes(const std::string& lh, const std::string& rh) { hash->Update(lh.data(), lh.size()); hash->Update(rh.data(), rh.size()); - std::string result; - hash->Finish(base::WriteInto(&result, crypto::kSHA256Length + 1), - crypto::kSHA256Length); + std::string result(crypto::kSHA256Length, '\0'); + hash->Finish(result.data(), result.size()); return result; } diff --git a/naiveproxy/src/net/cert/internal/revocation_checker.cc b/naiveproxy/src/net/cert/internal/revocation_checker.cc index 352a4c5130..f6efa5ab3b 100644 --- a/naiveproxy/src/net/cert/internal/revocation_checker.cc +++ b/naiveproxy/src/net/cert/internal/revocation_checker.cc @@ -4,13 +4,13 @@ #include "net/cert/internal/revocation_checker.h" +#include #include #include #include "base/logging.h" #include "crypto/sha2.h" #include "net/cert/cert_net_fetcher.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/common_cert_errors.h" #include "third_party/boringssl/src/pki/crl.h" #include "third_party/boringssl/src/pki/ocsp.h" @@ -39,7 +39,7 @@ bool CheckCertRevocation(const bssl::ParsedCertificateList& certs, const RevocationPolicy& policy, base::TimeTicks deadline, std::string_view stapled_ocsp_response, - absl::optional max_age_seconds, + std::optional max_age_seconds, CertNetFetcher* net_fetcher, bssl::CertErrors* cert_errors, bssl::OCSPVerifyResult* stapled_ocsp_verify_result) { @@ -110,7 +110,7 @@ bool CheckCertRevocation(const bssl::ParsedCertificateList& certs, // TODO(eroman): Duplication of work if there are multiple URLs to try. // TODO(eroman): Are there cases where we would need to POST instead? - absl::optional get_url_str = + std::optional get_url_str = CreateOCSPGetURL(cert, issuer_cert, ocsp_uri); if (!get_url_str.has_value()) { // An unexpected failure from BoringSSL, or the input was too large to @@ -308,7 +308,7 @@ void CheckValidatedChainRevocation( std::string_view stapled_ocsp = (i == 0) ? stapled_leaf_ocsp_response : std::string_view(); - absl::optional max_age_seconds; + std::optional max_age_seconds; if (policy.enforce_baseline_requirements) { max_age_seconds = ((i == 0) ? kMaxRevocationLeafUpdateAge : kMaxRevocationIntermediateUpdateAge) diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc index 9137ca1337..5b2cd42ab3 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.cc @@ -3,13 +3,15 @@ // found in the LICENSE file. #include "net/cert/internal/trust_store_chrome.h" + +#include + #include "base/containers/span.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "net/cert/root_store_proto_lite/root_store.pb.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/pool.h" #include "third_party/boringssl/src/pki/cert_errors.h" #include "third_party/boringssl/src/pki/parsed_certificate.h" @@ -32,7 +34,7 @@ ChromeRootStoreData& ChromeRootStoreData::operator=( ChromeRootStoreData& ChromeRootStoreData::operator=( ChromeRootStoreData&& other) = default; -absl::optional +std::optional ChromeRootStoreData::CreateChromeRootStoreData( const chrome_root_store::RootStore& proto) { ChromeRootStoreData root_store_data; @@ -40,7 +42,7 @@ ChromeRootStoreData::CreateChromeRootStoreData( for (auto& anchor : proto.trust_anchors()) { if (anchor.der().empty()) { LOG(ERROR) << "Error anchor with empty DER in update"; - return absl::nullopt; + return std::nullopt; } auto parsed = bssl::ParsedCertificate::Create( @@ -48,7 +50,7 @@ ChromeRootStoreData::CreateChromeRootStoreData( net::x509_util::DefaultParseCertificateOptions(), nullptr); if (!parsed) { LOG(ERROR) << "Error parsing cert for update"; - return absl::nullopt; + return std::nullopt; } root_store_data.anchors_.push_back(std::move(parsed)); } diff --git a/naiveproxy/src/net/cert/internal/trust_store_chrome.h b/naiveproxy/src/net/cert/internal/trust_store_chrome.h index b262fb2369..3317d07811 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_chrome.h +++ b/naiveproxy/src/net/cert/internal/trust_store_chrome.h @@ -5,9 +5,10 @@ #ifndef NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_ #define NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_ +#include + #include "base/containers/span.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/trust_store.h" #include "third_party/boringssl/src/pki/trust_store_in_memory.h" @@ -27,9 +28,9 @@ struct ChromeRootCertInfo { class NET_EXPORT ChromeRootStoreData { public: // CreateChromeRootStoreData converts |proto| into a usable - // ChromeRootStoreData object. Returns absl::nullopt if the passed in + // ChromeRootStoreData object. Returns std::nullopt if the passed in // proto has errors in it (e.g. an unparsable DER-encoded certificate). - static absl::optional CreateChromeRootStoreData( + static std::optional CreateChromeRootStoreData( const chrome_root_store::RootStore& proto); ~ChromeRootStoreData(); diff --git a/naiveproxy/src/net/cert/internal/trust_store_mac.cc b/naiveproxy/src/net/cert/internal/trust_store_mac.cc index 303ccefa67..f06ac21f77 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_mac.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_mac.cc @@ -214,8 +214,7 @@ TrustStatus IsCertificateTrustedForPolicyInDomain( // more than one domain it would generally be because one domain is // overriding the setting in the next, so it would only get done once anyway. base::apple::ScopedCFTypeRef cert_handle = - x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), - cert->der_cert().Length()); + x509_util::CreateSecCertificateFromBytes(cert->der_cert()); if (!cert_handle) return TrustStatus::UNSPECIFIED; @@ -264,8 +263,7 @@ TrustStatus IsCertificateTrustedForPolicy(const bssl::ParsedCertificate* cert, TrustStatus IsCertificateTrustedForPolicy(const bssl::ParsedCertificate* cert, const CFStringRef policy_oid) { base::apple::ScopedCFTypeRef cert_handle = - x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), - cert->der_cert().Length()); + x509_util::CreateSecCertificateFromBytes(cert->der_cert()); if (!cert_handle) return TrustStatus::UNSPECIFIED; @@ -432,7 +430,7 @@ class TrustDomainCacheFullCerts { SHA256HashValue CalculateFingerprint256(const bssl::der::Input& buffer) { SHA256HashValue sha256; - SHA256(buffer.UnsafeData(), buffer.Length(), sha256.data); + SHA256(buffer.data(), buffer.size(), sha256.data); return sha256; } @@ -1165,8 +1163,7 @@ base::apple::ScopedCFTypeRef TrustStoreMac::GetMacNormalizedIssuer( // There does not appear to be any public API to get the normalized version // of a Name without creating a SecCertificate. base::apple::ScopedCFTypeRef cert_handle( - x509_util::CreateSecCertificateFromBytes(cert->der_cert().UnsafeData(), - cert->der_cert().Length())); + x509_util::CreateSecCertificateFromBytes(cert->der_cert())); if (!cert_handle) { LOG(ERROR) << "CreateCertBufferFromBytes"; return name_data; diff --git a/naiveproxy/src/net/cert/internal/trust_store_nss.cc b/naiveproxy/src/net/cert/internal/trust_store_nss.cc index dab68a63e4..e1fe2b8395 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_nss.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_nss.cc @@ -157,8 +157,8 @@ void TrustStoreNSS::SyncGetIssuersOf(const bssl::ParsedCertificate* cert, // Use the original issuer value instead of the normalized version. NSS does a // less extensive normalization in its Name comparisons, so our normalized // version may not match the unnormalized version. - name.len = cert->tbs().issuer_tlv.Length(); - name.data = const_cast(cert->tbs().issuer_tlv.UnsafeData()); + name.len = cert->tbs().issuer_tlv.size(); + name.data = const_cast(cert->tbs().issuer_tlv.data()); // |validOnly| in CERT_CreateSubjectCertList controls whether to return only // certs that are valid at |sorttime|. Expiration isn't meaningful for trust @@ -278,8 +278,8 @@ bssl::CertificateTrust TrustStoreNSS::GetTrust( } SECItem der_cert; - der_cert.data = const_cast(cert->der_cert().UnsafeData()); - der_cert.len = base::checked_cast(cert->der_cert().Length()); + der_cert.data = const_cast(cert->der_cert().data()); + der_cert.len = base::checked_cast(cert->der_cert().size()); der_cert.type = siDERCertBuffer; // Find a matching NSS certificate object, if any. Note that NSS trust diff --git a/naiveproxy/src/net/cert/internal/trust_store_win.cc b/naiveproxy/src/net/cert/internal/trust_store_win.cc index 0c61da3f1e..636c223484 100644 --- a/naiveproxy/src/net/cert/internal/trust_store_win.cc +++ b/naiveproxy/src/net/cert/internal/trust_store_win.cc @@ -264,7 +264,7 @@ class TrustStoreWin::Impl { !disallowed_cert_store_.get()) { return; } - base::span issuer_span = cert->issuer_tlv().AsSpan(); + base::span issuer_span = cert->issuer_tlv(); CERT_NAME_BLOB cert_issuer_blob; cert_issuer_blob.cbData = static_cast(issuer_span.size()); @@ -293,7 +293,7 @@ class TrustStoreWin::Impl { return bssl::CertificateTrust::ForUnspecified(); } - base::span cert_span = cert->der_cert().AsSpan(); + base::span cert_span = cert->der_cert(); base::SHA1Digest cert_hash = base::SHA1HashSpan(cert_span); CRYPT_HASH_BLOB cert_hash_blob; cert_hash_blob.cbData = static_cast(cert_hash.size()); diff --git a/naiveproxy/src/net/cert/mock_cert_verifier.cc b/naiveproxy/src/net/cert/mock_cert_verifier.cc index bd83d0f84f..f21caf652e 100644 --- a/naiveproxy/src/net/cert/mock_cert_verifier.cc +++ b/naiveproxy/src/net/cert/mock_cert_verifier.cc @@ -23,6 +23,48 @@ namespace net { +namespace { +// Helper function for setting the appropriate CertStatus given a net::Error. +CertStatus MapNetErrorToCertStatus(int error) { + switch (error) { + case ERR_CERT_COMMON_NAME_INVALID: + return CERT_STATUS_COMMON_NAME_INVALID; + case ERR_CERT_DATE_INVALID: + return CERT_STATUS_DATE_INVALID; + case ERR_CERT_AUTHORITY_INVALID: + return CERT_STATUS_AUTHORITY_INVALID; + case ERR_CERT_NO_REVOCATION_MECHANISM: + return CERT_STATUS_NO_REVOCATION_MECHANISM; + case ERR_CERT_UNABLE_TO_CHECK_REVOCATION: + return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; + case ERR_CERTIFICATE_TRANSPARENCY_REQUIRED: + return CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED; + case ERR_CERT_REVOKED: + return CERT_STATUS_REVOKED; + case ERR_CERT_INVALID: + return CERT_STATUS_INVALID; + case ERR_CERT_WEAK_SIGNATURE_ALGORITHM: + return CERT_STATUS_WEAK_SIGNATURE_ALGORITHM; + case ERR_CERT_NON_UNIQUE_NAME: + return CERT_STATUS_NON_UNIQUE_NAME; + case ERR_CERT_WEAK_KEY: + return CERT_STATUS_WEAK_KEY; + case ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: + return CERT_STATUS_PINNED_KEY_MISSING; + case ERR_CERT_NAME_CONSTRAINT_VIOLATION: + return CERT_STATUS_NAME_CONSTRAINT_VIOLATION; + case ERR_CERT_VALIDITY_TOO_LONG: + return CERT_STATUS_VALIDITY_TOO_LONG; + case ERR_CERT_SYMANTEC_LEGACY: + return CERT_STATUS_SYMANTEC_LEGACY; + case ERR_CERT_KNOWN_INTERCEPTION_BLOCKED: + return (CERT_STATUS_KNOWN_INTERCEPTION_BLOCKED | CERT_STATUS_REVOKED); + default: + return 0; + } +} +} // namespace + struct MockCertVerifier::Rule { Rule(scoped_refptr cert_arg, const std::string& hostname_arg, diff --git a/naiveproxy/src/net/cert/signed_tree_head.cc b/naiveproxy/src/net/cert/signed_tree_head.cc index 41c205341d..e255fcd920 100644 --- a/naiveproxy/src/net/cert/signed_tree_head.cc +++ b/naiveproxy/src/net/cert/signed_tree_head.cc @@ -39,8 +39,7 @@ void PrintTo(const SignedTreeHead& sth, std::ostream* os) { << "\t\"tree_size\": " << sth.tree_size << ",\n" << "\t\"sha256_root_hash\": \"" << base::HexEncode(sth.sha256_root_hash, kSthRootHashLength) - << "\",\n\t\"log_id\": \"" - << base::HexEncode(sth.log_id.data(), sth.log_id.size()) << "\"\n" + << "\",\n\t\"log_id\": \"" << base::HexEncode(sth.log_id) << "\"\n" << "}"; } diff --git a/naiveproxy/src/net/cert/x509_certificate.cc b/naiveproxy/src/net/cert/x509_certificate.cc index 30f5cd87bc..f23121ac4a 100644 --- a/naiveproxy/src/net/cert/x509_certificate.cc +++ b/naiveproxy/src/net/cert/x509_certificate.cc @@ -18,6 +18,7 @@ #include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/pickle.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/time/time.h" #include "crypto/openssl_util.h" @@ -79,7 +80,7 @@ void SplitOnChar(std::string_view src, [[nodiscard]] bool ParseSequenceValue(const bssl::der::Input& tlv, bssl::der::Input* value) { bssl::der::Parser parser(tlv); - return parser.ReadTag(bssl::der::kSequence, value) && !parser.HasMore(); + return parser.ReadTag(CBS_ASN1_SEQUENCE, value) && !parser.HasMore(); } // Normalize |cert|'s Issuer and store it in |out_normalized_issuer|, returning @@ -435,7 +436,7 @@ bool X509Certificate::IsIssuedByEncoded( // static bool X509Certificate::VerifyHostname( - const std::string& hostname, + std::string_view hostname, const std::vector& cert_san_dns_names, const std::vector& cert_san_ip_addrs) { DCHECK(!hostname.empty()); @@ -453,8 +454,9 @@ bool X509Certificate::VerifyHostname( // Presented identifier(s) == name(s) the server knows itself as, in its cert. // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. - const std::string host_or_ip = hostname.find(':') != std::string::npos ? - "[" + hostname + "]" : hostname; + const std::string host_or_ip = hostname.find(':') != std::string::npos + ? base::StrCat({"[", hostname, "]"}) + : std::string(hostname); url::CanonHostInfo host_info; std::string reference_name = CanonicalizeHost(host_or_ip, &host_info); @@ -566,7 +568,7 @@ bool X509Certificate::VerifyHostname( return false; } -bool X509Certificate::VerifyNameMatch(const std::string& hostname) const { +bool X509Certificate::VerifyNameMatch(std::string_view hostname) const { std::vector dns_names, ip_addrs; GetSubjectAltName(&dns_names, &ip_addrs); return VerifyHostname(hostname, dns_names, ip_addrs); diff --git a/naiveproxy/src/net/cert/x509_certificate.h b/naiveproxy/src/net/cert/x509_certificate.h index 351bc87a44..ad138a534e 100644 --- a/naiveproxy/src/net/cert/x509_certificate.h +++ b/naiveproxy/src/net/cert/x509_certificate.h @@ -206,7 +206,7 @@ class NET_EXPORT X509Certificate // Verifies that |hostname| matches this certificate. // Does not verify that the certificate is valid, only that the certificate // matches this host. - bool VerifyNameMatch(const std::string& hostname) const; + bool VerifyNameMatch(std::string_view hostname) const; // Returns the PEM encoded data from a DER encoded certificate. If the // return value is true, then the PEM encoded certificate is written to @@ -320,7 +320,7 @@ class NET_EXPORT X509Certificate // extension, if present. Note these IP addresses are NOT ascii-encoded: // they must be 4 or 16 bytes of network-ordered data, for IPv4 and IPv6 // addresses, respectively. - static bool VerifyHostname(const std::string& hostname, + static bool VerifyHostname(std::string_view hostname, const std::vector& cert_san_dns_names, const std::vector& cert_san_ip_addrs); diff --git a/naiveproxy/src/net/cert/x509_util.cc b/naiveproxy/src/net/cert/x509_util.cc index 0bdd9a4c81..00e5ba024c 100644 --- a/naiveproxy/src/net/cert/x509_util.cc +++ b/naiveproxy/src/net/cert/x509_util.cc @@ -548,9 +548,7 @@ bool SignatureVerifierInitWithCertificate( } } - return verifier->VerifyInit( - signature_algorithm, signature, - base::make_span(tbs.spki_tlv.UnsafeData(), tbs.spki_tlv.Length())); + return verifier->VerifyInit(signature_algorithm, signature, tbs.spki_tlv); } bool HasRsaPkcs1Sha1Signature(const CRYPTO_BUFFER* cert_buffer) { diff --git a/naiveproxy/src/net/cert/x509_util_android.cc b/naiveproxy/src/net/cert/x509_util_android.cc index a136bdb149..1fb7431568 100644 --- a/naiveproxy/src/net/cert/x509_util_android.cc +++ b/naiveproxy/src/net/cert/x509_util_android.cc @@ -5,7 +5,7 @@ #include "net/cert/cert_database.h" #include "net/net_jni_headers/X509Util_jni.h" -using base::android::JavaParamRef; +using jni_zero::JavaParamRef; namespace net { diff --git a/naiveproxy/src/net/cert/x509_util_apple.cc b/naiveproxy/src/net/cert/x509_util_apple.cc index cc371cd451..5768b14e7b 100644 --- a/naiveproxy/src/net/cert/x509_util_apple.cc +++ b/naiveproxy/src/net/cert/x509_util_apple.cc @@ -40,13 +40,13 @@ bssl::UniquePtr CertBufferFromSecCertificate( } // namespace base::apple::ScopedCFTypeRef CreateSecCertificateFromBytes( - const uint8_t* data, - size_t length) { - base::apple::ScopedCFTypeRef cert_data( - CFDataCreate(kCFAllocatorDefault, reinterpret_cast(data), - base::checked_cast(length))); - if (!cert_data) + base::span data) { + base::apple::ScopedCFTypeRef cert_data(CFDataCreate( + kCFAllocatorDefault, reinterpret_cast(data.data()), + base::checked_cast(data.size()))); + if (!cert_data) { return base::apple::ScopedCFTypeRef(); + } return base::apple::ScopedCFTypeRef( SecCertificateCreateWithData(nullptr, cert_data.get())); @@ -54,8 +54,7 @@ base::apple::ScopedCFTypeRef CreateSecCertificateFromBytes( base::apple::ScopedCFTypeRef CreateSecCertificateFromX509Certificate(const X509Certificate* cert) { - return CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(cert->cert_buffer()), - CRYPTO_BUFFER_len(cert->cert_buffer())); + return CreateSecCertificateFromBytes(CryptoBufferAsSpan(cert->cert_buffer())); } base::apple::ScopedCFTypeRef @@ -74,15 +73,14 @@ CreateSecCertificateArrayForX509Certificate( return base::apple::ScopedCFTypeRef(); std::string bytes; base::apple::ScopedCFTypeRef sec_cert( - CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(cert->cert_buffer()), - CRYPTO_BUFFER_len(cert->cert_buffer()))); - if (!sec_cert) + CreateSecCertificateFromBytes(CryptoBufferAsSpan(cert->cert_buffer()))); + if (!sec_cert) { return base::apple::ScopedCFTypeRef(); + } CFArrayAppendValue(cert_list.get(), sec_cert.get()); for (const auto& intermediate : cert->intermediate_buffers()) { base::apple::ScopedCFTypeRef intermediate_cert( - CreateSecCertificateFromBytes(CRYPTO_BUFFER_data(intermediate.get()), - CRYPTO_BUFFER_len(intermediate.get()))); + CreateSecCertificateFromBytes(CryptoBufferAsSpan(intermediate.get()))); if (!intermediate_cert) { if (invalid_intermediate_behavior == InvalidIntermediateBehavior::kFail) return base::apple::ScopedCFTypeRef(); diff --git a/naiveproxy/src/net/cert/x509_util_apple.h b/naiveproxy/src/net/cert/x509_util_apple.h index 775be2b16e..323f5fe5cd 100644 --- a/naiveproxy/src/net/cert/x509_util_apple.h +++ b/naiveproxy/src/net/cert/x509_util_apple.h @@ -9,6 +9,7 @@ #include #include "base/apple/scoped_cftyperef.h" +#include "base/containers/span.h" #include "base/memory/scoped_refptr.h" #include "net/base/hash_value.h" #include "net/base/net_export.h" @@ -20,7 +21,7 @@ namespace x509_util { // Creates a SecCertificate handle from the DER-encoded representation. // Returns NULL on failure. NET_EXPORT base::apple::ScopedCFTypeRef -CreateSecCertificateFromBytes(const uint8_t* data, size_t length); +CreateSecCertificateFromBytes(base::span data); // Returns a SecCertificate representing |cert|, or NULL on failure. NET_EXPORT base::apple::ScopedCFTypeRef diff --git a/naiveproxy/src/net/cert/x509_util_nss.cc b/naiveproxy/src/net/cert/x509_util_nss.cc index 0cddbb5a63..24578249ef 100644 --- a/naiveproxy/src/net/cert/x509_util_nss.cc +++ b/naiveproxy/src/net/cert/x509_util_nss.cc @@ -179,8 +179,7 @@ ScopedCERTCertificate CreateCERTCertificateFromBytes( ScopedCERTCertificate CreateCERTCertificateFromX509Certificate( const X509Certificate* cert) { return CreateCERTCertificateFromBytes( - base::make_span(CRYPTO_BUFFER_data(cert->cert_buffer()), - CRYPTO_BUFFER_len(cert->cert_buffer()))); + CryptoBufferAsSpan(cert->cert_buffer())); } ScopedCERTCertificateList CreateCERTCertificateListFromX509Certificate( @@ -200,9 +199,8 @@ ScopedCERTCertificateList CreateCERTCertificateListFromX509Certificate( return {}; nss_chain.push_back(std::move(nss_cert)); for (const auto& intermediate : cert->intermediate_buffers()) { - ScopedCERTCertificate nss_intermediate = CreateCERTCertificateFromBytes( - base::make_span(CRYPTO_BUFFER_data(intermediate.get()), - CRYPTO_BUFFER_len(intermediate.get()))); + ScopedCERTCertificate nss_intermediate = + CreateCERTCertificateFromBytes(CryptoBufferAsSpan(intermediate.get())); if (!nss_intermediate) { if (invalid_intermediate_behavior == InvalidIntermediateBehavior::kFail) return {}; diff --git a/naiveproxy/src/net/cookies/canonical_cookie.cc b/naiveproxy/src/net/cookies/canonical_cookie.cc index 02636104ea..fb0fe2873f 100644 --- a/naiveproxy/src/net/cookies/canonical_cookie.cc +++ b/naiveproxy/src/net/cookies/canonical_cookie.cc @@ -45,6 +45,7 @@ #include "net/cookies/canonical_cookie.h" #include +#include #include #include "base/containers/contains.h" @@ -67,7 +68,6 @@ #include "net/cookies/cookie_util.h" #include "net/cookies/parsed_cookie.h" #include "net/http/http_util.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/url_canon.h" #include "url/url_util.h" @@ -393,7 +393,7 @@ CanonicalCookie::CanonicalCookie( bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieSourceScheme source_scheme, int source_port) : name_(std::move(name)), @@ -556,8 +556,8 @@ std::unique_ptr CanonicalCookie::Create( const GURL& url, const std::string& cookie_line, const base::Time& creation_time, - absl::optional server_time, - absl::optional cookie_partition_key, + std::optional server_time, + std::optional cookie_partition_key, bool block_truncated, CookieInclusionStatus* status) { // Put a pointer on the stack so the rest of the function can assign to it if @@ -655,7 +655,7 @@ std::unique_ptr CanonicalCookie::Create( if (!partition_has_nonce) UMA_HISTOGRAM_BOOLEAN("Cookie.IsPartitionedValid", is_partitioned_valid); } else if (!partition_has_nonce) { - cookie_partition_key = absl::nullopt; + cookie_partition_key = std::nullopt; } if (!status->IsInclude()) @@ -762,7 +762,7 @@ std::unique_ptr CanonicalCookie::CreateSanitizedCookie( bool http_only, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieInclusionStatus* status) { // Put a pointer on the stack so the rest of the function can assign to it if // the default nullptr is passed in. @@ -951,7 +951,7 @@ std::unique_ptr CanonicalCookie::FromStorage( bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieSourceScheme source_scheme, int source_port) { // We check source_port here because it could have concievably been @@ -996,7 +996,7 @@ std::unique_ptr CanonicalCookie::CreateUnsafeCookieForTesting( bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieSourceScheme source_scheme, int source_port) { return std::make_unique( @@ -1025,13 +1025,13 @@ void CanonicalCookie::SetSourcePort(int port) { } CanonicalCookie::UniqueCookieKey CanonicalCookie::UniqueKey() const { - absl::optional source_scheme = + std::optional source_scheme = cookie_util::IsSchemeBoundCookiesEnabled() - ? absl::make_optional(source_scheme_) - : absl::nullopt; - absl::optional source_port = cookie_util::IsPortBoundCookiesEnabled() - ? absl::make_optional(source_port_) - : absl::nullopt; + ? std::make_optional(source_scheme_) + : std::nullopt; + std::optional source_port = cookie_util::IsPortBoundCookiesEnabled() + ? std::make_optional(source_port_) + : std::nullopt; return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme, source_port); @@ -1039,10 +1039,10 @@ CanonicalCookie::UniqueCookieKey CanonicalCookie::UniqueKey() const { CanonicalCookie::UniqueDomainCookieKey CanonicalCookie::UniqueDomainKey() const { - absl::optional source_scheme = + std::optional source_scheme = cookie_util::IsSchemeBoundCookiesEnabled() - ? absl::make_optional(source_scheme_) - : absl::nullopt; + ? std::make_optional(source_scheme_) + : std::nullopt; return std::make_tuple(partition_key_, name_, domain_, path_, source_scheme); } @@ -1103,13 +1103,15 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL( } switch (cookie_access_scheme) { case CookieAccessScheme::kNonCryptographic: - if (IsSecure()) + if (SecureAttribute()) { status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_SECURE_ONLY); + } break; case CookieAccessScheme::kTrustworthy: is_allowed_to_access_secure_cookies = true; - if (IsSecure() || (cookie_util::IsSchemeBoundCookiesEnabled() && - source_scheme_ == CookieSourceScheme::kSecure)) { + if (SecureAttribute() || + (cookie_util::IsSchemeBoundCookiesEnabled() && + source_scheme_ == CookieSourceScheme::kSecure)) { status.AddWarningReason( CookieInclusionStatus:: WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC); @@ -1247,13 +1249,13 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL( // were created before "SameSite=None requires Secure" was enabled (as // SameSite=None insecure cookies cannot be set while the options are on). if (params.access_semantics != CookieAccessSemantics::LEGACY && - SameSite() == CookieSameSite::NO_RESTRICTION && !IsSecure()) { + SameSite() == CookieSameSite::NO_RESTRICTION && !SecureAttribute()) { status.AddExclusionReason( CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE); } ApplySameSiteCookieWarningToStatus(SameSite(), effective_same_site, - IsSecure(), + SecureAttribute(), options.same_site_cookie_context(), &status, false /* is_cookie_being_set */); @@ -1311,7 +1313,7 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( const CookieOptions& options, const CookieAccessParams& params, const std::vector& cookieable_schemes, - const absl::optional& cookie_access_result) const { + const std::optional& cookie_access_result) const { CookieAccessResult access_result; if (cookie_access_result) { access_result = *cookie_access_result; @@ -1332,7 +1334,7 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( switch (access_scheme) { case CookieAccessScheme::kNonCryptographic: access_result.is_allowed_to_access_secure_cookies = false; - if (IsSecure()) { + if (SecureAttribute()) { access_result.status.AddExclusionReason( CookieInclusionStatus::EXCLUDE_SECURE_ONLY); } @@ -1345,7 +1347,7 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( case CookieAccessScheme::kTrustworthy: access_result.is_allowed_to_access_secure_cookies = true; - if (IsSecure()) { + if (SecureAttribute()) { // OK, but want people aware of this. // Note, we also want to apply this warning to cookies whose source // scheme is kSecure but are set by non-cryptographic (but trustworthy) @@ -1370,7 +1372,7 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( // Unless legacy access semantics are in effect, SameSite=None cookies without // the Secure attribute will be rejected. if (params.access_semantics != CookieAccessSemantics::LEGACY && - SameSite() == CookieSameSite::NO_RESTRICTION && !IsSecure()) { + SameSite() == CookieSameSite::NO_RESTRICTION && !SecureAttribute()) { DVLOG(net::cookie_util::kVlogSetCookies) << "SetCookie() rejecting insecure cookie with SameSite=None."; access_result.status.AddExclusionReason( @@ -1426,7 +1428,7 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext( } ApplySameSiteCookieWarningToStatus( - SameSite(), access_result.effective_same_site, IsSecure(), + SameSite(), access_result.effective_same_site, SecureAttribute(), options.same_site_cookie_context(), &access_result.status, true /* is_cookie_being_set */); @@ -1594,8 +1596,9 @@ std::string CanonicalCookie::BuildCookieAttributesLine( cookie_line += "; path=" + cookie.Path(); if (cookie.ExpiryDate() != base::Time()) cookie_line += "; expires=" + HttpUtil::TimeFormatHTTP(cookie.ExpiryDate()); - if (cookie.IsSecure()) + if (cookie.SecureAttribute()) { cookie_line += "; secure"; + } if (cookie.IsHttpOnly()) cookie_line += "; httponly"; if (cookie.IsPartitioned() && @@ -1812,7 +1815,7 @@ bool CanonicalCookie::IsCookiePartitionedValid(const GURL& url, CookieAndLineWithAccessResult::CookieAndLineWithAccessResult() = default; CookieAndLineWithAccessResult::CookieAndLineWithAccessResult( - absl::optional cookie, + std::optional cookie, std::string cookie_string, CookieAccessResult access_result) : cookie(std::move(cookie)), diff --git a/naiveproxy/src/net/cookies/canonical_cookie.h b/naiveproxy/src/net/cookies/canonical_cookie.h index 599b17b834..64e945b02a 100644 --- a/naiveproxy/src/net/cookies/canonical_cookie.h +++ b/naiveproxy/src/net/cookies/canonical_cookie.h @@ -6,6 +6,7 @@ #define NET_COOKIES_CANONICAL_COOKIE_H_ #include +#include #include #include #include @@ -22,7 +23,6 @@ #include "net/cookies/cookie_inclusion_status.h" #include "net/cookies/cookie_options.h" #include "net/cookies/cookie_partition_key.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/third_party/mozilla/url_parse.h" class GURL; @@ -57,7 +57,7 @@ class NET_EXPORT CanonicalCookie { public: // StrictlyUniqueCookieKey always populates the cookie's source scheme and // source port. - using StrictlyUniqueCookieKey = std::tuple, + using StrictlyUniqueCookieKey = std::tuple, /*name=*/std::string, /*domain=*/std::string, /*path=*/std::string, @@ -66,20 +66,20 @@ class NET_EXPORT CanonicalCookie { // Conditionally populates the source scheme and source port depending on the // state of their associated feature. - using UniqueCookieKey = std::tuple, + using UniqueCookieKey = std::tuple, /*name=*/std::string, /*domain=*/std::string, /*path=*/std::string, - absl::optional, - /*source_port=*/absl::optional>; + std::optional, + /*source_port=*/std::optional>; // Same as UniqueCookieKey but for use with Domain cookies, which do not // consider the source_port. - using UniqueDomainCookieKey = std::tuple, + using UniqueDomainCookieKey = std::tuple, /*name=*/std::string, /*domain=*/std::string, /*path=*/std::string, - absl::optional>; + std::optional>; CanonicalCookie(); CanonicalCookie(const CanonicalCookie& other); @@ -107,7 +107,7 @@ class NET_EXPORT CanonicalCookie { bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset, int source_port = url::PORT_UNSPECIFIED); @@ -128,7 +128,7 @@ class NET_EXPORT CanonicalCookie { // // The partition_key argument only needs to be present if the cookie line // contains the Partitioned attribute. If the cookie line will never contain - // that attribute, you should use absl::nullopt to indicate you intend to + // that attribute, you should use std::nullopt to indicate you intend to // always create an unpartitioned cookie. If partition_key has a value but the // cookie line does not contain the Partitioned attribute, the resulting // cookie will be unpartitioned. If the partition_key is null, then the cookie @@ -144,8 +144,8 @@ class NET_EXPORT CanonicalCookie { const GURL& url, const std::string& cookie_line, const base::Time& creation_time, - absl::optional server_time, - absl::optional cookie_partition_key, + std::optional server_time, + std::optional cookie_partition_key, bool block_truncated = true, CookieInclusionStatus* status = nullptr); @@ -167,7 +167,7 @@ class NET_EXPORT CanonicalCookie { bool http_only, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieInclusionStatus* status = nullptr); // FromStorage is a factory method which is meant for creating a new @@ -190,7 +190,7 @@ class NET_EXPORT CanonicalCookie { bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key, + std::optional partition_key, CookieSourceScheme source_scheme, int source_port); @@ -209,7 +209,7 @@ class NET_EXPORT CanonicalCookie { bool httponly, CookieSameSite same_site, CookiePriority priority, - absl::optional partition_key = absl::nullopt, + std::optional partition_key = std::nullopt, CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset, int source_port = url::PORT_UNSPECIFIED); @@ -236,12 +236,12 @@ class NET_EXPORT CanonicalCookie { const base::Time& LastAccessDate() const { return last_access_date_; } const base::Time& LastUpdateDate() const { return last_update_date_; } bool IsPersistent() const { return !expiry_date_.is_null(); } - bool IsSecure() const { return secure_; } + bool SecureAttribute() const { return secure_; } bool IsHttpOnly() const { return httponly_; } CookieSameSite SameSite() const { return same_site_; } CookiePriority Priority() const { return priority_; } bool IsPartitioned() const { return partition_key_.has_value(); } - const absl::optional& PartitionKey() const { + const std::optional& PartitionKey() const { return partition_key_; } @@ -261,10 +261,17 @@ class NET_EXPORT CanonicalCookie { // Returns whether this cookie is Partitioned and its partition key matches a // a same-site context by checking if the cookies domain site is the same as // the partition key's site. + // This function should not be used for third-party cookie blocking + // enforcement-related decisions. That logic should rely on `IsPartitioned`. + // These functions are for recording metrics about partitioned cookie usage. // Returns false if the cookie has no partition key. bool IsFirstPartyPartitioned() const; // Returns whether the cookie is partitioned in a third-party context. + // This function should not be used for third-party cookie blocking + // enforcement-related decisions. That logic should rely on `IsPartitioned`. + // These functions are for recording metrics about partitioned cookie usage. + // Returns false if the cookie has no partition key. bool IsThirdPartyPartitioned() const; // Returns the cookie's domain, with the leading dot removed, if present. @@ -445,8 +452,8 @@ class NET_EXPORT CanonicalCookie { const CookieOptions& options, const CookieAccessParams& params, const std::vector& cookieable_schemes, - const absl::optional& cookie_access_result = - absl::nullopt) const; + const std::optional& cookie_access_result = + std::nullopt) const; std::string DebugString() const; @@ -628,13 +635,13 @@ class NET_EXPORT CanonicalCookie { bool httponly_{false}; CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION}; CookiePriority priority_{COOKIE_PRIORITY_MEDIUM}; - // This will be absl::nullopt for all cookies not set with the Partitioned + // This will be std::nullopt for all cookies not set with the Partitioned // attribute or without a nonce. If the value is non-null, then the cookie // will only be delivered when the top-frame site matches the partition key // and the nonce (if present). If the partition key is non-null and opaque, // this means the Partitioned cookie was created on an opaque origin or with // a nonce. - absl::optional partition_key_; + std::optional partition_key_; CookieSourceScheme source_scheme_{CookieSourceScheme::kUnset}; // This can be [0,65535], PORT_UNSPECIFIED, or PORT_INVALID. // PORT_UNSPECIFIED is used for cookies which already existed in the cookie @@ -647,7 +654,7 @@ class NET_EXPORT CanonicalCookie { // canonical cookie object may not be available. struct NET_EXPORT CookieAndLineWithAccessResult { CookieAndLineWithAccessResult(); - CookieAndLineWithAccessResult(absl::optional cookie, + CookieAndLineWithAccessResult(std::optional cookie, std::string cookie_string, CookieAccessResult access_result); CookieAndLineWithAccessResult( @@ -661,7 +668,7 @@ struct NET_EXPORT CookieAndLineWithAccessResult { ~CookieAndLineWithAccessResult(); - absl::optional cookie; + std::optional cookie; std::string cookie_string; CookieAccessResult access_result; }; diff --git a/naiveproxy/src/net/cookies/canonical_cookie_test_helpers.h b/naiveproxy/src/net/cookies/canonical_cookie_test_helpers.h index b3236fc026..e3fee19c53 100644 --- a/naiveproxy/src/net/cookies/canonical_cookie_test_helpers.h +++ b/naiveproxy/src/net/cookies/canonical_cookie_test_helpers.h @@ -103,6 +103,13 @@ MATCHER_P(HasExclusionReason, reason, "") { result_listener); } +// Helper for checking that status.exemption_reason() == reason. +MATCHER_P(HasExactlyExemptionReason, reason, "") { + CookieInclusionStatus status = arg; + return testing::ExplainMatchResult(true, status.exemption_reason() == reason, + result_listener); +} + // Helper for checking that status.HasExactlyExclusionReasonsForTesting(reasons) // == true. MATCHER_P(HasExactlyExclusionReasonsForTesting, reasons, "") { diff --git a/naiveproxy/src/net/cookies/cookie_access_delegate.h b/naiveproxy/src/net/cookies/cookie_access_delegate.h index 0eec2486fa..f43f9d8e73 100644 --- a/naiveproxy/src/net/cookies/cookie_access_delegate.h +++ b/naiveproxy/src/net/cookies/cookie_access_delegate.h @@ -5,6 +5,8 @@ #ifndef NET_COOKIES_COOKIE_ACCESS_DELEGATE_H_ #define NET_COOKIES_COOKIE_ACCESS_DELEGATE_H_ +#include + #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/functional/callback_forward.h" @@ -16,7 +18,6 @@ #include "net/first_party_sets/first_party_set_entry.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -59,7 +60,7 @@ class NET_EXPORT CookieAccessDelegate { // with the result. The callback will be invoked iff the return value is // nullopt; i.e. a result will be provided via return value or callback, but // not both, and not neither. - [[nodiscard]] virtual absl::optional< + [[nodiscard]] virtual std::optional< std::pair> ComputeFirstPartySetMetadataMaybeAsync( const net::SchemefulSite& site, @@ -76,7 +77,7 @@ class NET_EXPORT CookieAccessDelegate { // with the result. The callback will be invoked iff the return value is // nullopt; i.e. a result will be provided via return value or callback, but // not both, and not neither. - [[nodiscard]] virtual absl::optional< + [[nodiscard]] virtual std::optional< base::flat_map> FindFirstPartySetEntries( const base::flat_set& sites, diff --git a/naiveproxy/src/net/cookies/cookie_change_dispatcher.cc b/naiveproxy/src/net/cookies/cookie_change_dispatcher.cc index e91df544ec..c0a8c304bb 100644 --- a/naiveproxy/src/net/cookies/cookie_change_dispatcher.cc +++ b/naiveproxy/src/net/cookies/cookie_change_dispatcher.cc @@ -7,31 +7,22 @@ namespace net { const char* CookieChangeCauseToString(CookieChangeCause cause) { - const char* cause_string = "INVALID"; switch (cause) { case CookieChangeCause::INSERTED: - cause_string = "inserted"; - break; + return "inserted"; case CookieChangeCause::EXPLICIT: - cause_string = "explicit"; - break; + return "explicit"; case CookieChangeCause::UNKNOWN_DELETION: - cause_string = "unknown"; - break; + return "unknown"; case CookieChangeCause::OVERWRITE: - cause_string = "overwrite"; - break; + return "overwrite"; case CookieChangeCause::EXPIRED: - cause_string = "expired"; - break; + return "expired"; case CookieChangeCause::EVICTED: - cause_string = "evicted"; - break; + return "evicted"; case CookieChangeCause::EXPIRED_OVERWRITE: - cause_string = "expired_overwrite"; - break; + return "expired_overwrite"; } - return cause_string; } CookieChangeInfo::CookieChangeInfo() = default; diff --git a/naiveproxy/src/net/cookies/cookie_change_dispatcher.h b/naiveproxy/src/net/cookies/cookie_change_dispatcher.h index 62cfee9048..68f9db18ce 100644 --- a/naiveproxy/src/net/cookies/cookie_change_dispatcher.h +++ b/naiveproxy/src/net/cookies/cookie_change_dispatcher.h @@ -140,7 +140,7 @@ class CookieChangeDispatcher { AddCallbackForCookie( const GURL& url, const std::string& name, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) = 0; // Observe changes to the cookies that would be sent for a request to `url`. @@ -153,7 +153,7 @@ class CookieChangeDispatcher { [[nodiscard]] virtual std::unique_ptr AddCallbackForUrl( const GURL& url, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) = 0; // Observe all the CookieStore's changes. diff --git a/naiveproxy/src/net/cookies/cookie_deletion_info.h b/naiveproxy/src/net/cookies/cookie_deletion_info.h index 40f444398c..c1d82f996d 100644 --- a/naiveproxy/src/net/cookies/cookie_deletion_info.h +++ b/naiveproxy/src/net/cookies/cookie_deletion_info.h @@ -5,6 +5,7 @@ #ifndef NET_COOKIES_COOKIE_DELETION_INFO_H_ #define NET_COOKIES_COOKIE_DELETION_INFO_H_ +#include #include #include @@ -12,7 +13,6 @@ #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_constants.h" #include "net/cookies/cookie_partition_key_collection.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -111,14 +111,14 @@ struct NET_EXPORT CookieDeletionInfo { SessionControl session_control = SessionControl::IGNORE_CONTROL; // If has a value then cookie.Host() must equal |host|. - absl::optional host; + std::optional host; // If has a value then cookie.Name() must equal |name|. - absl::optional name; + std::optional name; // If has a value then will match if the cookie being evaluated would be // included for a request of |url|. - absl::optional url; + std::optional url; // If has a value then any cookie with a domain/ip contained in this set // will be deleted (assuming other fields match). @@ -128,7 +128,7 @@ struct NET_EXPORT CookieDeletionInfo { // Note: |domains_and_ips_to_ignore| takes precedence. For example if this // has a value of ["A", "B"] and |domains_and_ips_to_ignore| is ["B", "C"] // then only "A" will be deleted. - absl::optional> domains_and_ips_to_delete; + std::optional> domains_and_ips_to_delete; // If has a value then any cookie with a domain/ip contained in this set // will be ignored (and not deleted). @@ -136,10 +136,10 @@ struct NET_EXPORT CookieDeletionInfo { // ".example.com". // // See precedence note above. - absl::optional> domains_and_ips_to_ignore; + std::optional> domains_and_ips_to_ignore; // Used only for testing purposes. - absl::optional value_for_testing; + std::optional value_for_testing; // Cookie partition collection. Partitioned cookies are not deleted if their // partition key is not in the collection. By default, it clears cookies in diff --git a/naiveproxy/src/net/cookies/cookie_inclusion_status.cc b/naiveproxy/src/net/cookies/cookie_inclusion_status.cc index b6cf92b53d..f84724c75d 100644 --- a/naiveproxy/src/net/cookies/cookie_inclusion_status.cc +++ b/naiveproxy/src/net/cookies/cookie_inclusion_status.cc @@ -5,8 +5,11 @@ #include "net/cookies/cookie_inclusion_status.h" #include +#include +#include #include +#include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/strings/strcat.h" #include "url/gurl.h" @@ -29,6 +32,19 @@ CookieInclusionStatus::CookieInclusionStatus(WarningReason warning) { warning_reasons_[warning] = true; } +CookieInclusionStatus::CookieInclusionStatus( + std::vector exclusions, + std::vector warnings, + ExemptionReason exemption) { + for (ExclusionReason reason : exclusions) { + exclusion_reasons_[reason] = true; + } + for (WarningReason warning : warnings) { + warning_reasons_[warning] = true; + } + exemption_reason_ = exemption; +} + CookieInclusionStatus::CookieInclusionStatus( const CookieInclusionStatus& other) = default; @@ -38,7 +54,8 @@ CookieInclusionStatus& CookieInclusionStatus::operator=( bool CookieInclusionStatus::operator==( const CookieInclusionStatus& other) const { return exclusion_reasons_ == other.exclusion_reasons_ && - warning_reasons_ == other.warning_reasons_; + warning_reasons_ == other.warning_reasons_ && + exemption_reason_ == other.exemption_reason_; } bool CookieInclusionStatus::operator!=( @@ -52,10 +69,11 @@ bool CookieInclusionStatus::operator<( "use .ullong() instead"); static_assert(NUM_WARNING_REASONS <= sizeof(unsigned long) * CHAR_BIT, "use .ullong() instead"); - return std::make_pair(exclusion_reasons_.to_ulong(), - warning_reasons_.to_ulong()) < - std::make_pair(other.exclusion_reasons_.to_ulong(), - other.warning_reasons_.to_ulong()); + return std::make_tuple(exclusion_reasons_.to_ulong(), + warning_reasons_.to_ulong(), exemption_reason_) < + std::make_tuple(other.exclusion_reasons_.to_ulong(), + other.warning_reasons_.to_ulong(), + other.exemption_reason_); } bool CookieInclusionStatus::IsInclude() const { @@ -79,6 +97,8 @@ void CookieInclusionStatus::AddExclusionReason(ExclusionReason reason) { // If the cookie would be excluded for reasons unrelated to 3pcd, don't bother // warning about 3pcd. MaybeClearThirdPartyPhaseoutReason(); + // If the cookie would have been excluded, clear the exemption reason. + exemption_reason_ = ExemptionReason::kNone; } void CookieInclusionStatus::RemoveExclusionReason(ExclusionReason reason) { @@ -90,6 +110,12 @@ void CookieInclusionStatus::RemoveExclusionReasons( exclusion_reasons_ = ExclusionReasonsWithout(reasons); } +void CookieInclusionStatus::MaybeSetExemptionReason(ExemptionReason reason) { + if (IsInclude() && exemption_reason_ == ExemptionReason::kNone) { + exemption_reason_ = reason; + } +} + CookieInclusionStatus::ExclusionReasonBitset CookieInclusionStatus::ExclusionReasonsWithout( const std::vector& reasons) const { @@ -275,8 +301,7 @@ std::string CookieInclusionStatus::GetDebugString() const { // Add warning if (!ShouldWarn()) { - base::StrAppend(&out, {"DO_NOT_WARN"}); - return out; + base::StrAppend(&out, {"DO_NOT_WARN, "}); } constexpr std::pair warning_reasons[] = { @@ -322,8 +347,42 @@ std::string CookieInclusionStatus::GetDebugString() const { base::StrAppend(&out, {reason.second, ", "}); } - // Strip trailing comma and space. - out.erase(out.end() - 2, out.end()); + // Add exemption reason + if (exemption_reason() == CookieInclusionStatus::ExemptionReason::kNone) { + base::StrAppend(&out, {"NO_EXEMPTION"}); + return out; + } + + std::string_view reason; + switch (exemption_reason()) { + case ExemptionReason::kUserSetting: + reason = "ExemptionUserSetting"; + break; + case ExemptionReason::k3PCDMetadata: + reason = "Exemption3PCDMetadata"; + break; + case ExemptionReason::k3PCDDeprecationTrial: + reason = "Exemption3PCDDeprecationTrial"; + break; + case ExemptionReason::k3PCDHeuristics: + reason = "Exemption3PCDHeuristics"; + break; + case ExemptionReason::kEnterprisePolicy: + reason = "ExemptionEnterprisePolicy"; + break; + case ExemptionReason::kStorageAccess: + reason = "ExemptionStorageAccess"; + break; + case ExemptionReason::kTopLevelStorageAccess: + reason = "ExemptionTopLevelStorageAccess"; + break; + case ExemptionReason::kCorsOptIn: + reason = "ExemptionCorsOptIn"; + break; + case ExemptionReason::kNone: + NOTREACHED_NORETURN(); + }; + base::StrAppend(&out, {reason}); return out; } @@ -353,18 +412,28 @@ bool CookieInclusionStatus::ValidateExclusionAndWarningFromWire( } CookieInclusionStatus CookieInclusionStatus::MakeFromReasonsForTesting( - std::vector reasons, - std::vector warnings) { + std::vector exclusions, + std::vector warnings, + ExemptionReason exemption, + bool use_literal) { + CookieInclusionStatus literal_status(exclusions, warnings, exemption); + if (use_literal) { + return literal_status; + } CookieInclusionStatus status; - for (ExclusionReason reason : reasons) { + for (ExclusionReason reason : exclusions) { status.AddExclusionReason(reason); } for (WarningReason warning : warnings) { status.AddWarningReason(warning); } + status.MaybeSetExemptionReason(exemption); + + CHECK_EQ(status, literal_status); return status; } +// TODO(shuuran): Consolidate reasons in this method. bool CookieInclusionStatus::ExcludedByUserPreferences() const { if (HasOnlyExclusionReason(ExclusionReason::EXCLUDE_USER_PREFERENCES) || HasOnlyExclusionReason(ExclusionReason::EXCLUDE_THIRD_PARTY_PHASEOUT)) { diff --git a/naiveproxy/src/net/cookies/cookie_inclusion_status.h b/naiveproxy/src/net/cookies/cookie_inclusion_status.h index 98d8012e54..6d97671584 100644 --- a/naiveproxy/src/net/cookies/cookie_inclusion_status.h +++ b/naiveproxy/src/net/cookies/cookie_inclusion_status.h @@ -266,6 +266,32 @@ class NET_EXPORT CookieInclusionStatus { kMaxValue = kLaxCrossLaxSecure }; + // Types of reasons why a cookie should-have-been-blocked by 3pcd got + // exempted and included. + enum class ExemptionReason { + // The default exemption reason. The cookie with this reason could either be + // included, or blocked due to 3pcd-unrelated reasons. + kNone = 0, + // For user explicit settings, including User bypass. + kUserSetting = 1, + // For 3PCD metadata . + k3PCDMetadata = 2, + // For 3PCD 1P and 3P deprecation trial. + k3PCDDeprecationTrial = 3, + // For 3PCD heuristics. + k3PCDHeuristics = 4, + // For Enterprise Policy : CookieAllowedForUrls and BlockThirdPartyCookies. + kEnterprisePolicy = 5, + kStorageAccess = 6, + kTopLevelStorageAccess = 7, + // For CorsException in the ABA contexts, which the inner iframe is + // same-site with the top-level site but has cross-site ancestor(s). + kCorsOptIn = 8, + + // Keep last. + kMaxValue = kCorsOptIn + }; + using ExclusionReasonBitset = std::bitset; using WarningReasonBitset = std::bitset; @@ -276,8 +302,12 @@ class NET_EXPORT CookieInclusionStatus { // Make a status that contains the given exclusion reason. explicit CookieInclusionStatus(ExclusionReason reason); // Makes a status that contains the given exclusion reason and warning. + // TODO(shuuran): only called in tests, use `MakeFromReasonsForTesting` + // instead. CookieInclusionStatus(ExclusionReason reason, WarningReason warning); // Makes a status that contains the given warning. + // TODO(shuuran): only called in tests, use `MakeFromReasonsForTesting` + // instead. explicit CookieInclusionStatus(WarningReason warning); // Copyable. @@ -308,6 +338,12 @@ class NET_EXPORT CookieInclusionStatus { // Remove multiple exclusion reasons. void RemoveExclusionReasons(const std::vector& reasons); + // Only updates exemption reason if the cookie was not already excluded and + // doesn't already have an exemption reason. + void MaybeSetExemptionReason(ExemptionReason reason); + + ExemptionReason exemption_reason() const { return exemption_reason_; } + // If the cookie would have been excluded for reasons other than // SameSite-related reasons, don't bother warning about it (clear the // warning). @@ -365,16 +401,21 @@ class NET_EXPORT CookieInclusionStatus { bool HasExactlyWarningReasonsForTesting( std::vector reasons) const; - // Validates mojo data, since mojo does not support bitsets. + // Validates mojo data, since mojo does not support bitsets. ExemptionReason + // is omitted intendedly. // TODO(crbug.com/1310444): Improve serialization validation comments // and check for mutually exclusive values. static bool ValidateExclusionAndWarningFromWire(uint32_t exclusion_reasons, uint32_t warning_reasons); - // Makes a status that contains the given exclusion reasons and warning. + // Makes a status that contains the given reasons. If 'use_literal' is true, + // this method permits status to have reason combinations that cannot occur + // under normal circumstances; otherwise it can cause a CHECK failure. static CookieInclusionStatus MakeFromReasonsForTesting( - std::vector reasons, - std::vector warnings = std::vector()); + std::vector exclusions, + std::vector warnings = std::vector(), + ExemptionReason exemption = ExemptionReason::kNone, + bool use_literal = false); // Returns true if the cookie was excluded because of user preferences. // HasOnlyExclusionReason(EXCLUDE_USER_PREFERENCES) will not return true for @@ -385,9 +426,16 @@ class NET_EXPORT CookieInclusionStatus { void ResetForTesting() { exclusion_reasons_.reset(); warning_reasons_.reset(); + exemption_reason_ = ExemptionReason::kNone; } private: + // Makes a status that contains the exact given exclusion reason and warning + // and exemption. + CookieInclusionStatus(std::vector exclusions, + std::vector warnings, + ExemptionReason exemption); + // Returns the `exclusion_reasons_` with the given `reasons` unset. ExclusionReasonBitset ExclusionReasonsWithout( const std::vector& reasons) const; @@ -402,6 +450,9 @@ class NET_EXPORT CookieInclusionStatus { // A bit vector of the applicable warning reasons. WarningReasonBitset warning_reasons_; + + // A cookie can only have at most one exemption reason. + ExemptionReason exemption_reason_ = ExemptionReason::kNone; }; NET_EXPORT inline std::ostream& operator<<(std::ostream& os, diff --git a/naiveproxy/src/net/cookies/cookie_monster.cc b/naiveproxy/src/net/cookies/cookie_monster.cc index 643279afbb..545288009f 100644 --- a/naiveproxy/src/net/cookies/cookie_monster.cc +++ b/naiveproxy/src/net/cookies/cookie_monster.cc @@ -46,6 +46,7 @@ #include #include +#include #include #include @@ -81,7 +82,6 @@ #include "net/http/http_util.h" #include "net/log/net_log.h" #include "net/log/net_log_values.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" #include "url/third_party/mozilla/url_parse.h" #include "url/url_canon.h" @@ -247,10 +247,11 @@ void SplitCookieVectorIntoSecureAndNonSecure( CookieMonster::CookieItVector* non_secure_cookie_its) { DCHECK(secure_cookie_its && non_secure_cookie_its); for (const auto& curit : cookie_its) { - if (curit->second->IsSecure()) + if (curit->second->SecureAttribute()) { secure_cookie_its->push_back(curit); - else + } else { non_secure_cookie_its->push_back(curit); + } } } @@ -314,7 +315,7 @@ bool IsCookieEligibleForEviction(CookiePriority current_priority_level, bool protect_secure_cookies, const CanonicalCookie* cookie) { if (cookie->Priority() == current_priority_level && protect_secure_cookies) - return !cookie->IsSecure(); + return !cookie->SecureAttribute(); return cookie->Priority() == current_priority_level; } @@ -326,8 +327,9 @@ size_t CountCookiesForPossibleDeletion( size_t cookies_count = 0U; for (const auto& cookie : *cookies) { if (cookie->second->Priority() == priority) { - if (!protect_secure_cookies || cookie->second->IsSecure()) + if (!protect_secure_cookies || cookie->second->SecureAttribute()) { cookies_count++; + } } } return cookies_count; @@ -343,7 +345,7 @@ void HistogramExpirationDuration(const CanonicalCookie& cookie, int expiration_duration_minutes = (cookie.ExpiryDate() - creation_time).InMinutes(); - if (cookie.IsSecure()) { + if (cookie.SecureAttribute()) { UMA_HISTOGRAM_CUSTOM_COUNTS("Cookie.ExpirationDurationMinutesSecure", expiration_duration_minutes, 1, kMinutesInTenYears, 50); @@ -425,7 +427,7 @@ void CookieMonster::SetCanonicalCookieAsync( const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result) { + std::optional cookie_access_result) { DCHECK(cookie->IsCanonical()); std::string domain = cookie->Domain(); @@ -1009,7 +1011,7 @@ void CookieMonster::EnsureCookiesMapIsValid() { // Ensure no equivalent cookies for this host. TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end, - absl::nullopt); + std::nullopt); } for (auto cookie_partition_it = partitioned_cookies_.begin(); @@ -1028,7 +1030,7 @@ void CookieMonster::EnsureCookiesMapIsValid() { // Ensure no equivalent cookies for this host and cookie partition key. TrimDuplicateCookiesForKey(key, cur_range_begin, cur_range_end, - absl::make_optional(cur_cookie_partition_it)); + std::make_optional(cur_cookie_partition_it)); } } } @@ -1043,7 +1045,7 @@ void CookieMonster::TrimDuplicateCookiesForKey( const std::string& key, CookieMap::iterator begin, CookieMap::iterator end, - absl::optional cookie_partition_it) { + std::optional cookie_partition_it) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // Set of cookies ordered by creation time. @@ -1387,7 +1389,7 @@ void CookieMonster::MaybeDeleteEquivalentCookieAndUpdateStatus( bool already_expired, base::Time* creation_date_to_inherit, CookieInclusionStatus* status, - absl::optional cookie_partition_it) { + std::optional cookie_partition_it) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(!status->HasExclusionReason( CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE)); @@ -1419,7 +1421,8 @@ void CookieMonster::MaybeDeleteEquivalentCookieAndUpdateStatus( // equivalence is slightly more inclusive than the usual IsEquivalent() one. // // See: https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone - if (cur_existing_cookie->IsSecure() && !allowed_to_set_secure_cookie && + if (cur_existing_cookie->SecureAttribute() && + !allowed_to_set_secure_cookie && cookie_being_set.IsEquivalentForSecureCookieMatching( *cur_existing_cookie)) { // Hold onto this for additional Netlogging later if we end up preserving @@ -1551,7 +1554,7 @@ void CookieMonster::LogCookieTypeToUMA( ? 1 << COOKIE_TYPE_SAME_SITE : 0; type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0; - type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0; + type_sample |= cc->SecureAttribute() ? 1 << COOKIE_TYPE_SECURE : 0; UMA_HISTOGRAM_EXACT_LINEAR("Cookie.Type", type_sample, (1 << COOKIE_TYPE_LAST_ENTRY)); } @@ -1611,7 +1614,7 @@ CookieMonster::InternalInsertPartitionedCookie( true); } - return std::make_pair(partition_it, cookie_it); + return std::pair(partition_it, cookie_it); } void CookieMonster::SetCanonicalCookie( @@ -1619,7 +1622,7 @@ void CookieMonster::SetCanonicalCookie( const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result) { + std::optional cookie_access_result) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); bool delegate_treats_url_as_trustworthy = @@ -1643,7 +1646,7 @@ void CookieMonster::SetCanonicalCookie( base::Time creation_date_to_inherit; - absl::optional cookie_partition_it; + std::optional cookie_partition_it; bool should_try_to_delete_duplicates = true; if (cc->IsPartitioned()) { @@ -1653,7 +1656,7 @@ void CookieMonster::SetCanonicalCookie( // duplicates. should_try_to_delete_duplicates = false; } else { - cookie_partition_it = absl::make_optional(it); + cookie_partition_it = std::make_optional(it); } } @@ -1692,10 +1695,8 @@ void CookieMonster::SetCanonicalCookie( } } - bool is_partitioned_cookie = cc->IsPartitioned(); - CookiePartitionKey cookie_partition_key; - if (is_partitioned_cookie) - cookie_partition_key = cc->PartitionKey().value(); + std::optional cookie_partition_key = cc->PartitionKey(); + CHECK_EQ(cc->IsPartitioned(), cookie_partition_key.has_value()); // Realize that we might be setting an expired cookie, and the only point // was to delete the cookie which we've already done. @@ -1711,10 +1712,10 @@ void CookieMonster::SetCanonicalCookie( // it was added to evaluate has been implemented and standardized. CookieSource cookie_source_sample = (source_url.SchemeIsCryptographic() - ? (cc->IsSecure() + ? (cc->SecureAttribute() ? CookieSource::kSecureCookieCryptographicScheme : CookieSource::kNonsecureCookieCryptographicScheme) - : (cc->IsSecure() + : (cc->SecureAttribute() ? CookieSource::kSecureCookieNoncryptographicScheme : CookieSource::kNonsecureCookieNoncryptographicScheme)); UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSourceScheme", @@ -1726,7 +1727,7 @@ void CookieMonster::SetCanonicalCookie( cc->SetCreationDate(creation_date_to_inherit); } - if (is_partitioned_cookie) { + if (cookie_partition_key.has_value()) { InternalInsertPartitionedCookie(key, std::move(cc), true, access_result); } else { @@ -1742,9 +1743,9 @@ void CookieMonster::SetCanonicalCookie( // make sure that we garbage collect... We can also make the assumption // that if a cookie was set, in the common case it will be used soon after, // and we will purge the expired cookies in GetCookies(). - if (is_partitioned_cookie) { - GarbageCollectPartitionedCookies(creation_date, cookie_partition_key, - key); + if (cookie_partition_key.has_value()) { + GarbageCollectPartitionedCookies(creation_date, + cookie_partition_key.value(), key); } else { GarbageCollect(creation_date, key); } @@ -2424,7 +2425,7 @@ bool CookieMonster::DoRecordPeriodicStats() { GURL(base::StrCat({url::kHttpsScheme, "://", domain}))); } } - absl::optional> + std::optional> maybe_sets = cookie_access_delegate()->FindFirstPartySetEntries( sites, base::BindOnce(&CookieMonster::RecordPeriodicFirstPartySetsStats, @@ -2568,8 +2569,7 @@ void CookieMonster::DoCookieCallbackForHostOrDomain( key, base::BindOnce(&CookieMonster::OnKeyLoaded, weak_ptr_factory_.GetWeakPtr(), key)); it = tasks_pending_for_key_ - .insert(std::make_pair( - key, base::circular_deque())) + .emplace(key, base::circular_deque()) .first; } it->second.push_back(std::move(callback)); @@ -2620,19 +2620,19 @@ CookieMonster::IsCookieSentToSamePortThatSetIt( return CookieSentToSamePort::kNo; } -absl::optional CookieMonster::SiteHasCookieInOtherPartition( +std::optional CookieMonster::SiteHasCookieInOtherPartition( const net::SchemefulSite& site, - const absl::optional& partition_key) const { + const std::optional& partition_key) const { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); // If the partition key is null, it implies the partitioned cookies feature is // not enabled. if (!partition_key) - return absl::nullopt; + return std::nullopt; std::string domain = site.GetURL().host(); if (store_ && !finished_fetching_all_cookies_ && !keys_loaded_.count(domain)) { - return absl::nullopt; + return std::nullopt; } for (const auto& it : partitioned_cookies_) { diff --git a/naiveproxy/src/net/cookies/cookie_monster.h b/naiveproxy/src/net/cookies/cookie_monster.h index 6871ed30ed..e8202c955a 100644 --- a/naiveproxy/src/net/cookies/cookie_monster.h +++ b/naiveproxy/src/net/cookies/cookie_monster.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -35,7 +36,6 @@ #include "net/cookies/cookie_monster_change_dispatcher.h" #include "net/cookies/cookie_store.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -184,8 +184,8 @@ class NET_EXPORT CookieMonster : public CookieStore { const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result = - absl::nullopt) override; + std::optional cookie_access_result = + std::nullopt) override; void GetCookieListWithOptionsAsync(const GURL& url, const CookieOptions& options, const CookiePartitionKeyCollection& s, @@ -208,9 +208,9 @@ class NET_EXPORT CookieMonster : public CookieStore { CookieChangeDispatcher& GetChangeDispatcher() override; void SetCookieableSchemes(const std::vector& schemes, SetCookieableSchemesCallback callback) override; - absl::optional SiteHasCookieInOtherPartition( + std::optional SiteHasCookieInOtherPartition( const net::SchemefulSite& site, - const absl::optional& partition_key) const override; + const std::optional& partition_key) const override; // Enables writing session cookies into the cookie database. If this this // method is called, it must be called before first use of the instance @@ -401,7 +401,7 @@ class NET_EXPORT CookieMonster : public CookieStore { const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result = absl::nullopt); + std::optional cookie_access_result = std::nullopt); void GetAllCookies(GetAllCookiesCallback callback); @@ -480,7 +480,7 @@ class NET_EXPORT CookieMonster : public CookieStore { const std::string& key, CookieMap::iterator begin, CookieMap::iterator end, - absl::optional cookie_partition_it); + std::optional cookie_partition_it); void SetDefaultCookieableSchemes(); @@ -536,7 +536,7 @@ class NET_EXPORT CookieMonster : public CookieStore { bool already_expired, base::Time* creation_date_to_inherit, CookieInclusionStatus* status, - absl::optional cookie_partition_it); + std::optional cookie_partition_it); // Inserts `cc` into cookies_. Returns an iterator that points to the inserted // cookie in `cookies_`. Guarantee: all iterators to `cookies_` remain valid. diff --git a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc index 61bd41e5a2..1e04b43f26 100644 --- a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc +++ b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.cc @@ -147,7 +147,7 @@ std::unique_ptr CookieMonsterChangeDispatcher::AddCallbackForCookie( const GURL& url, const std::string& name, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -163,7 +163,7 @@ CookieMonsterChangeDispatcher::AddCallbackForCookie( std::unique_ptr CookieMonsterChangeDispatcher::AddCallbackForUrl( const GURL& url, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); diff --git a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.h b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.h index d6f449140b..03a9b7458c 100644 --- a/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.h +++ b/naiveproxy/src/net/cookies/cookie_monster_change_dispatcher.h @@ -54,11 +54,11 @@ class CookieMonsterChangeDispatcher : public CookieChangeDispatcher { [[nodiscard]] std::unique_ptr AddCallbackForCookie( const GURL& url, const std::string& name, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) override; [[nodiscard]] std::unique_ptr AddCallbackForUrl( const GURL& url, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) override; [[nodiscard]] std::unique_ptr AddCallbackForAllChanges(CookieChangeCallback callback) override; diff --git a/naiveproxy/src/net/cookies/cookie_monster_netlog_params.cc b/naiveproxy/src/net/cookies/cookie_monster_netlog_params.cc index 6679203568..ec330bcdf4 100644 --- a/naiveproxy/src/net/cookies/cookie_monster_netlog_params.cc +++ b/naiveproxy/src/net/cookies/cookie_monster_netlog_params.cc @@ -28,7 +28,7 @@ base::Value::Dict NetLogCookieMonsterCookieAdded( dict.Set("domain", cookie->Domain()); dict.Set("path", cookie->Path()); dict.Set("httponly", cookie->IsHttpOnly()); - dict.Set("secure", cookie->IsSecure()); + dict.Set("secure", cookie->SecureAttribute()); dict.Set("priority", CookiePriorityToString(cookie->Priority())); dict.Set("same_site", CookieSameSiteToString(cookie->SameSite())); dict.Set("is_persistent", cookie->IsPersistent()); diff --git a/naiveproxy/src/net/cookies/cookie_partition_key.cc b/naiveproxy/src/net/cookies/cookie_partition_key.cc index d3ba6de8eb..2645193f0c 100644 --- a/naiveproxy/src/net/cookies/cookie_partition_key.cc +++ b/naiveproxy/src/net/cookies/cookie_partition_key.cc @@ -19,7 +19,7 @@ CookiePartitionKey::CookiePartitionKey() = default; CookiePartitionKey::CookiePartitionKey( const SchemefulSite& site, - absl::optional nonce) + std::optional nonce) : site_(site), nonce_(nonce) {} CookiePartitionKey::CookiePartitionKey(const GURL& url) @@ -54,7 +54,7 @@ bool CookiePartitionKey::operator<(const CookiePartitionKey& other) const { } // static -bool CookiePartitionKey::Serialize(const absl::optional& in, +bool CookiePartitionKey::Serialize(const std::optional& in, std::string& out) { if (!in) { out = kEmptyCookiePartitionKey; @@ -72,9 +72,9 @@ bool CookiePartitionKey::Serialize(const absl::optional& in, // static bool CookiePartitionKey::Deserialize(const std::string& in, - absl::optional& out) { + std::optional& out) { if (in == kEmptyCookiePartitionKey) { - out = absl::nullopt; + out = std::nullopt; return true; } if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) { @@ -88,40 +88,40 @@ bool CookiePartitionKey::Deserialize(const std::string& in, DLOG(WARNING) << "Cannot deserialize opaque origin to CookiePartitionKey"; return false; } - out = absl::make_optional(CookiePartitionKey(schemeful_site, absl::nullopt)); + out = std::make_optional(CookiePartitionKey(schemeful_site, std::nullopt)); return true; } -absl::optional CookiePartitionKey::FromNetworkIsolationKey( +std::optional CookiePartitionKey::FromNetworkIsolationKey( const NetworkIsolationKey& network_isolation_key) { if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) { - return absl::nullopt; + return std::nullopt; } - const absl::optional& nonce = + const std::optional& nonce = network_isolation_key.GetNonce(); // Use frame site for nonced partitions. Since the nonce is unique, this still // creates a unique partition key. The reason we use the frame site is to // align CookiePartitionKey's implementation of nonced partitions with // StorageKey's. See https://crbug.com/1440765. - const absl::optional& partition_key_site = + const std::optional& partition_key_site = nonce ? network_isolation_key.GetFrameSiteForCookiePartitionKey( NetworkIsolationKey::CookiePartitionKeyPassKey()) : network_isolation_key.GetTopFrameSite(); if (!partition_key_site) - return absl::nullopt; + return std::nullopt; return net::CookiePartitionKey(*partition_key_site, nonce); } // static -absl::optional +std::optional CookiePartitionKey::FromStorageKeyComponents( const SchemefulSite& site, - const absl::optional& nonce) { + const std::optional& nonce) { if (!base::FeatureList::IsEnabled(features::kPartitionedCookies)) { - return absl::nullopt; + return std::nullopt; } return CookiePartitionKey::FromWire(site, nonce); } diff --git a/naiveproxy/src/net/cookies/cookie_partition_key.h b/naiveproxy/src/net/cookies/cookie_partition_key.h index 1c90d6ced7..3bd9385f00 100644 --- a/naiveproxy/src/net/cookies/cookie_partition_key.h +++ b/naiveproxy/src/net/cookies/cookie_partition_key.h @@ -5,12 +5,12 @@ #ifndef NET_COOKIES_COOKIE_PARTITION_KEY_H_ #define NET_COOKIES_COOKIE_PARTITION_KEY_H_ +#include #include #include "net/base/net_export.h" #include "net/base/network_isolation_key.h" #include "net/base/schemeful_site.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -43,26 +43,25 @@ class NET_EXPORT CookiePartitionKey { // TODO(crbug.com/1225444) Investigate ways to persist partition keys with // opaque origins if a browser session is restored. [[nodiscard]] static bool Serialize( - const absl::optional& in, + const std::optional& in, std::string& out); // Deserializes the result of the method above. - // If the result is absl::nullopt, the resulting cookie is not partitioned. + // If the result is std::nullopt, the resulting cookie is not partitioned. // // Returns if the resulting partition key is valid. - [[nodiscard]] static bool Deserialize( - const std::string& in, - absl::optional& out); + [[nodiscard]] static bool Deserialize(const std::string& in, + std::optional& out); static CookiePartitionKey FromURLForTesting( const GURL& url, - const absl::optional nonce = absl::nullopt) { + const std::optional nonce = std::nullopt) { return nonce ? CookiePartitionKey(SchemefulSite(url), nonce) : CookiePartitionKey(url); } // Create a partition key from a network isolation key. Partition key is // derived from the key's top-frame site. - static absl::optional FromNetworkIsolationKey( + static std::optional FromNetworkIsolationKey( const NetworkIsolationKey& network_isolation_key); // Create a new CookiePartitionKey from the site of an existing @@ -70,7 +69,7 @@ class NET_EXPORT CookiePartitionKey { // which were already created using Deserialize or FromNetworkIsolationKey. static CookiePartitionKey FromWire( const SchemefulSite& site, - absl::optional nonce = absl::nullopt) { + std::optional nonce = std::nullopt) { return CookiePartitionKey(site, nonce); } @@ -86,17 +85,17 @@ class NET_EXPORT CookiePartitionKey { // TODO(crbug.com/1225444) Consider removing this factory method and // `from_script_` flag when BlinkStorageKey is available in // ServiceWorkerGlobalScope. - static absl::optional FromScript() { - return absl::make_optional(CookiePartitionKey(true)); + static std::optional FromScript() { + return std::make_optional(CookiePartitionKey(true)); } // Create a new CookiePartitionKey from the components of a StorageKey. // Forwards to FromWire, but unlike that method in this one the optional nonce // argument has no default. It also checks that cookie partitioning is enabled // before returning a valid key, which FromWire does not check. - static absl::optional FromStorageKeyComponents( + static std::optional FromStorageKeyComponents( const SchemefulSite& top_level_site, - const absl::optional& nonce); + const std::optional& nonce); const SchemefulSite& site() const { return site_; } @@ -106,15 +105,15 @@ class NET_EXPORT CookiePartitionKey { // Cookie partition keys whose internal site is opaque cannot be serialized. bool IsSerializeable() const; - const absl::optional& nonce() const { return nonce_; } + const std::optional& nonce() const { return nonce_; } - static bool HasNonce(const absl::optional& key) { + static bool HasNonce(const std::optional& key) { return key && key->nonce(); } private: explicit CookiePartitionKey(const SchemefulSite& site, - absl::optional nonce); + std::optional nonce); explicit CookiePartitionKey(const GURL& url); explicit CookiePartitionKey(bool from_script); @@ -123,7 +122,7 @@ class NET_EXPORT CookiePartitionKey { // Having a nonce is a way to force a transient opaque `CookiePartitionKey` // for non-opaque origins. - absl::optional nonce_; + std::optional nonce_; }; // Used so that CookiePartitionKeys can be the arguments of DCHECK_EQ. diff --git a/naiveproxy/src/net/cookies/cookie_partition_key_collection.h b/naiveproxy/src/net/cookies/cookie_partition_key_collection.h index eac9659b22..7721100612 100644 --- a/naiveproxy/src/net/cookies/cookie_partition_key_collection.h +++ b/naiveproxy/src/net/cookies/cookie_partition_key_collection.h @@ -41,7 +41,7 @@ class NET_EXPORT CookiePartitionKeyCollection { } static CookiePartitionKeyCollection FromOptional( - const absl::optional& opt_key) { + const std::optional& opt_key) { return opt_key ? CookiePartitionKeyCollection(opt_key.value()) : CookiePartitionKeyCollection(); } diff --git a/naiveproxy/src/net/cookies/cookie_store.cc b/naiveproxy/src/net/cookies/cookie_store.cc index 8b73d3fd54..0299475d4d 100644 --- a/naiveproxy/src/net/cookies/cookie_store.cc +++ b/naiveproxy/src/net/cookies/cookie_store.cc @@ -43,10 +43,10 @@ void CookieStore::SetCookieAccessDelegate( cookie_access_delegate_ = std::move(delegate); } -absl::optional CookieStore::SiteHasCookieInOtherPartition( +std::optional CookieStore::SiteHasCookieInOtherPartition( const net::SchemefulSite& site, - const absl::optional& partition_key) const { - return absl::nullopt; + const std::optional& partition_key) const { + return std::nullopt; } } // namespace net diff --git a/naiveproxy/src/net/cookies/cookie_store.h b/naiveproxy/src/net/cookies/cookie_store.h index 61fd008fc0..3f0be99e0e 100644 --- a/naiveproxy/src/net/cookies/cookie_store.h +++ b/naiveproxy/src/net/cookies/cookie_store.h @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -21,7 +22,6 @@ #include "net/cookies/cookie_deletion_info.h" #include "net/cookies/cookie_options.h" #include "net/cookies/cookie_partition_key_collection.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -74,8 +74,8 @@ class NET_EXPORT CookieStore { const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result = - absl::nullopt) = 0; + std::optional cookie_access_result = + std::nullopt) = 0; // Obtains a CookieList for the given |url| and |options|. The returned // cookies are passed into |callback|, ordered by longest path, then earliest @@ -174,9 +174,9 @@ class NET_EXPORT CookieStore { // Will return nullopt if cookies have not finished loading. // If the partition key is null, the method assumes it is because partitioned // cookies are disabled. - virtual absl::optional SiteHasCookieInOtherPartition( + virtual std::optional SiteHasCookieInOtherPartition( const net::SchemefulSite& site, - const absl::optional& cookie_partition_key) const; + const std::optional& cookie_partition_key) const; private: // Used to determine whether a particular cookie should be subject to legacy diff --git a/naiveproxy/src/net/cookies/cookie_store_change_unittest.h b/naiveproxy/src/net/cookies/cookie_store_change_unittest.h index be89df1f31..925aef87fa 100644 --- a/naiveproxy/src/net/cookies/cookie_store_change_unittest.h +++ b/naiveproxy/src/net/cookies/cookie_store_change_unittest.h @@ -725,14 +725,14 @@ TYPED_TEST_P(CookieStoreChangeGlobalTest, PartitionedCookies) { this->CreateAndSetCookie( cs, GURL("https://www.example2.com"), "__Host-a=1; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))); this->CreateAndSetCookie( cs, GURL("https://www.example2.com"), "__Host-a=2; Secure; Path=/; Partitioned; Max-Age=7200", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com"), base::UnguessableToken::Create())); this->DeliverChangeNotifications(); @@ -747,7 +747,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, NoCookie) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -765,7 +765,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, InitialCookie) { this->DeliverChangeNotifications(); std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -781,7 +781,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, InsertOne) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -808,7 +808,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, InsertMany) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -852,7 +852,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, InsertFiltering) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -906,7 +906,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteOne) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -936,7 +936,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteTwo) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -985,7 +985,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeleteFiltering) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1051,7 +1051,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, Overwrite) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1095,7 +1095,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, OverwriteFiltering) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1191,7 +1191,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, OverwriteWithHttpOnly) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1252,7 +1252,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, Deregister) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1288,13 +1288,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterMultiple) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1345,7 +1345,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DispatchRace) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1372,7 +1372,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterRace) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1417,13 +1417,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DeregisterRaceMultiple) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1478,13 +1478,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsDisjoint) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_bar_com_.url(), absl::nullopt /* cookie_partition_key */, + this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1522,13 +1522,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsDomains) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_bar_com_.url(), absl::nullopt /* cookie_partition_key */, + this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1566,13 +1566,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsPaths) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1622,19 +1622,19 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, DifferentSubscriptionsFiltering) { std::vector cookie_changes_3; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_bar_com_.url(), absl::nullopt /* cookie_partition_key */, + this->http_bar_com_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); std::unique_ptr subscription3 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->www_foo_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->www_foo_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_3))); @@ -1699,13 +1699,13 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, MultipleSubscriptions) { std::vector cookie_changes_1, cookie_changes_2; std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForUrl( - this->http_www_foo_.url(), absl::nullopt /* cookie_partition_key */, + this->http_www_foo_.url(), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -1738,7 +1738,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, ChangeIncludesCookieAccessSemantics) { std::vector cookie_changes; std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForUrl( - GURL("http://domain1.test"), absl::nullopt /* cookie_partition_key */, + GURL("http://domain1.test"), std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1778,15 +1778,15 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies) { this->CreateAndSetCookie( cs, GURL("https://www.example.com/"), "__Host-b=2; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://sub.foo.com"))); // Partitioned cookie with a different partition key this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-c=3; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com"))); this->DeliverChangeNotifications(); @@ -1805,7 +1805,7 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies) { std::unique_ptr other_subscription = cs->GetChangeDispatcher().AddCallbackForUrl( GURL("https://www.example.com/"), - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&other_cookie_changes))); @@ -1813,8 +1813,8 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies) { this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-b=2; Secure; Path=/; Partitioned; Max-Age=7200", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))); this->DeliverChangeNotifications(); ASSERT_EQ(0u, other_cookie_changes.size()); @@ -1852,8 +1852,8 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies_WithNonce) { this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-a=2; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))); this->DeliverChangeNotifications(); ASSERT_EQ(0u, cookie_changes.size()); @@ -1862,8 +1862,8 @@ TYPED_TEST_P(CookieStoreChangeUrlTest, PartitionedCookies_WithNonce) { this->CreateAndSetCookie(cs, GURL("https://www.example.com"), "__Host-a=3; Secure; Path=/; Partitioned", CookieOptions::MakeAllInclusive(), - absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting( GURL("https://www.foo.com"), nonce)); this->DeliverChangeNotifications(); @@ -1879,7 +1879,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, NoCookie) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1898,7 +1898,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, InitialCookie) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1915,7 +1915,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, InsertOne) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1943,7 +1943,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, InsertTwo) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -1985,7 +1985,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, InsertFiltering) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2045,7 +2045,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteOne) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2076,7 +2076,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteTwo) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2121,7 +2121,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeleteFiltering) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2192,7 +2192,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, Overwrite) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2237,7 +2237,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, OverwriteFiltering) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2341,7 +2341,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, OverwriteWithHttpOnly) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2404,7 +2404,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, Deregister) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2444,14 +2444,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterMultiple) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2509,7 +2509,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DispatchRace) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2539,7 +2539,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterRace) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -2587,14 +2587,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DeregisterRaceMultiple) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2655,14 +2655,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsDisjoint) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_bar_com_.url(), "ghi", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2701,14 +2701,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsDomains) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_bar_com_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2747,14 +2747,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsNames) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "ghi", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2793,14 +2793,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsPaths) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2852,28 +2852,28 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, DifferentSubscriptionsFiltering) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "hij", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); std::unique_ptr subscription3 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_bar_com_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_3))); std::unique_ptr subscription4 = cs->GetChangeDispatcher().AddCallbackForCookie( this->www_foo_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_4))); @@ -2960,14 +2960,14 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, MultipleSubscriptions) { std::unique_ptr subscription1 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_1))); std::unique_ptr subscription2 = cs->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes_2))); @@ -2996,7 +2996,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, SubscriptionOutlivesStore) { std::unique_ptr subscription = this->GetCookieStore()->GetChangeDispatcher().AddCallbackForCookie( this->http_www_foo_.url(), "abc", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -3022,7 +3022,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, ChangeIncludesCookieAccessSemantics) { std::unique_ptr subscription = cs->GetChangeDispatcher().AddCallbackForCookie( GURL("http://domain1.test"), "cookie", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&cookie_changes))); @@ -3062,15 +3062,15 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies) { this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-a=2; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://sub.foo.com"))); // Partitioned cookie with a different partition key this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-a=3; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.bar.com"))); this->DeliverChangeNotifications(); @@ -3088,7 +3088,7 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies) { std::unique_ptr other_subscription = cs->GetChangeDispatcher().AddCallbackForCookie( GURL("https://www.example.com"), "__Host-a", - absl::nullopt /* cookie_partition_key */, + std::nullopt /* cookie_partition_key */, base::BindRepeating( &CookieStoreChangeTestBase::OnCookieChange, base::Unretained(&other_cookie_changes))); @@ -3096,8 +3096,8 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies) { this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-a=2; Secure; Path=/; Partitioned; Max-Age=7200", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))); this->DeliverChangeNotifications(); ASSERT_EQ(0u, other_cookie_changes.size()); @@ -3135,8 +3135,8 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies_WithNonce) { this->CreateAndSetCookie( cs, GURL("https://www.example.com"), "__Host-a=2; Secure; Path=/; Partitioned", - CookieOptions::MakeAllInclusive(), absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + CookieOptions::MakeAllInclusive(), std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting(GURL("https://www.foo.com"))); this->DeliverChangeNotifications(); ASSERT_EQ(0u, cookie_changes.size()); @@ -3145,8 +3145,8 @@ TYPED_TEST_P(CookieStoreChangeNamedTest, PartitionedCookies_WithNonce) { this->CreateAndSetCookie(cs, GURL("https://www.example.com"), "__Host-a=3; Secure; Path=/; Partitioned", CookieOptions::MakeAllInclusive(), - absl::nullopt /* server_time */, - absl::nullopt /* system_time */, + std::nullopt /* server_time */, + std::nullopt /* system_time */, CookiePartitionKey::FromURLForTesting( GURL("https://www.foo.com"), nonce)); this->DeliverChangeNotifications(); diff --git a/naiveproxy/src/net/cookies/cookie_store_test_helpers.cc b/naiveproxy/src/net/cookies/cookie_store_test_helpers.cc index 9c8d1701a8..031fcfc3b4 100644 --- a/naiveproxy/src/net/cookies/cookie_store_test_helpers.cc +++ b/naiveproxy/src/net/cookies/cookie_store_test_helpers.cc @@ -4,6 +4,7 @@ #include "net/cookies/cookie_store_test_helpers.h" +#include #include #include @@ -16,7 +17,6 @@ #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" #include "net/http/http_util.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" using net::registry_controlled_domains::GetDomainAndRegistry; @@ -51,7 +51,7 @@ std::unique_ptr DelayedCookieMonsterChangeDispatcher::AddCallbackForCookie( const GURL& url, const std::string& name, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) { ADD_FAILURE(); return nullptr; @@ -59,7 +59,7 @@ DelayedCookieMonsterChangeDispatcher::AddCallbackForCookie( std::unique_ptr DelayedCookieMonsterChangeDispatcher::AddCallbackForUrl( const GURL& url, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) { ADD_FAILURE(); return nullptr; @@ -98,7 +98,7 @@ void DelayedCookieMonster::SetCanonicalCookieAsync( const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - absl::optional cookie_access_result) { + std::optional cookie_access_result) { did_run_ = false; cookie_monster_->SetCanonicalCookieAsync( std::move(cookie), source_url, options, diff --git a/naiveproxy/src/net/cookies/cookie_store_test_helpers.h b/naiveproxy/src/net/cookies/cookie_store_test_helpers.h index ea91b1a4fe..da9caebda4 100644 --- a/naiveproxy/src/net/cookies/cookie_store_test_helpers.h +++ b/naiveproxy/src/net/cookies/cookie_store_test_helpers.h @@ -5,18 +5,17 @@ #ifndef NET_COOKIES_COOKIE_STORE_TEST_HELPERS_H_ #define NET_COOKIES_COOKIE_STORE_TEST_HELPERS_H_ -#include "net/cookies/cookie_monster.h" - #include +#include #include #include #include "base/functional/callback_forward.h" #include "base/synchronization/lock.h" #include "net/cookies/cookie_change_dispatcher.h" +#include "net/cookies/cookie_monster.h" #include "net/log/net_log_with_source.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -37,11 +36,11 @@ class DelayedCookieMonsterChangeDispatcher : public CookieChangeDispatcher { [[nodiscard]] std::unique_ptr AddCallbackForCookie( const GURL& url, const std::string& name, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) override; [[nodiscard]] std::unique_ptr AddCallbackForUrl( const GURL& url, - const absl::optional& cookie_partition_key, + const std::optional& cookie_partition_key, CookieChangeCallback callback) override; [[nodiscard]] std::unique_ptr AddCallbackForAllChanges(CookieChangeCallback callback) override; @@ -65,8 +64,8 @@ class DelayedCookieMonster : public CookieStore { const GURL& source_url, const CookieOptions& options, SetCookiesCallback callback, - const absl::optional cookie_access_result = - absl::nullopt) override; + const std::optional cookie_access_result = + std::nullopt) override; void GetCookieListWithOptionsAsync( const GURL& url, diff --git a/naiveproxy/src/net/cookies/cookie_store_unittest.h b/naiveproxy/src/net/cookies/cookie_store_unittest.h index 23542343f9..1959869d44 100644 --- a/naiveproxy/src/net/cookies/cookie_store_unittest.h +++ b/naiveproxy/src/net/cookies/cookie_store_unittest.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include "net/cookies/cookie_store_test_helpers.h" #include "net/cookies/test_cookie_access_delegate.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #if BUILDFLAG(IS_IOS) @@ -218,9 +218,9 @@ class CookieStoreTest : public testing::Test { const GURL& url, const std::string& cookie_line, const CookieOptions& options, - absl::optional server_time = absl::nullopt, - absl::optional system_time = absl::nullopt, - absl::optional cookie_partition_key = absl::nullopt) { + std::optional server_time = std::nullopt, + std::optional system_time = std::nullopt, + std::optional cookie_partition_key = std::nullopt) { // Ensure a different Creation date to guarantee sort order for testing static base::Time last = base::Time::Min(); last = base::Time::Now() == last ? last + base::Microseconds(1) @@ -266,8 +266,8 @@ class CookieStoreTest : public testing::Test { options.set_include_httponly(); options.set_same_site_cookie_context( net::CookieOptions::SameSiteCookieContext::MakeInclusive()); - return CreateAndSetCookie(cs, url, cookie_line, options, absl::nullopt, - absl::make_optional(system_time)); + return CreateAndSetCookie(cs, url, cookie_line, options, std::nullopt, + std::make_optional(system_time)); } bool SetCookieWithServerTime(CookieStore* cs, @@ -280,21 +280,21 @@ class CookieStoreTest : public testing::Test { options.set_same_site_cookie_context( net::CookieOptions::SameSiteCookieContext::MakeInclusive()); return CreateAndSetCookie(cs, url, cookie_line, options, - absl::make_optional(server_time)); + std::make_optional(server_time)); } bool SetCookie( CookieStore* cs, const GURL& url, const std::string& cookie_line, - absl::optional cookie_partition_key = absl::nullopt) { + std::optional cookie_partition_key = std::nullopt) { CookieOptions options; if (!CookieStoreTestTraits::supports_http_only) options.set_include_httponly(); options.set_same_site_cookie_context( net::CookieOptions::SameSiteCookieContext::MakeInclusive()); - return CreateAndSetCookie(cs, url, cookie_line, options, absl::nullopt, - absl::nullopt, cookie_partition_key); + return CreateAndSetCookie(cs, url, cookie_line, options, std::nullopt, + std::nullopt, cookie_partition_key); } CookieInclusionStatus CreateAndSetCookieReturnStatus( @@ -303,8 +303,8 @@ class CookieStoreTest : public testing::Test { const std::string& cookie_line) { CookieInclusionStatus create_status; auto cookie = CanonicalCookie::Create( - url, cookie_line, base::Time::Now(), /*server_time=*/absl::nullopt, - /*cookie_partition_key=*/absl::nullopt, /*block_truncated=*/true, + url, cookie_line, base::Time::Now(), /*server_time=*/std::nullopt, + /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true, &create_status); if (!cookie) return create_status; @@ -473,7 +473,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { std::unique_ptr cc(CanonicalCookie::CreateSanitizedCookie( this->www_foo_foo_.url(), "A", "B", std::string(), "/foo", one_hour_ago, one_hour_from_now, base::Time(), false, false, - CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, absl::nullopt)); + CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, std::nullopt)); ASSERT_TRUE(cc); EXPECT_TRUE(this->SetCanonicalCookie( cs, std::move(cc), this->www_foo_foo_.url(), true /*modify_httponly*/)); @@ -483,7 +483,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { cc = CanonicalCookie::CreateSanitizedCookie( this->www_foo_bar_.url(), "C", "D", this->www_foo_bar_.domain(), "/bar", two_hours_ago, base::Time(), one_hour_ago, false, true, - CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, absl::nullopt); + CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, std::nullopt); ASSERT_TRUE(cc); EXPECT_TRUE(this->SetCanonicalCookie( cs, std::move(cc), this->www_foo_bar_.url(), true /*modify_httponly*/)); @@ -495,7 +495,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { cc = CanonicalCookie::CreateSanitizedCookie( this->http_www_foo_.url(), "E", "F", std::string(), std::string(), base::Time(), base::Time(), base::Time(), true, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, absl::nullopt); + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt); ASSERT_TRUE(cc); EXPECT_FALSE(this->SetCanonicalCookie( cs, std::move(cc), this->http_www_foo_.url(), true /*modify_httponly*/)); @@ -503,7 +503,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { cc = CanonicalCookie::CreateSanitizedCookie( this->https_www_foo_.url(), "E", "F", std::string(), std::string(), base::Time(), base::Time(), base::Time(), true, false, - CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, absl::nullopt); + CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, std::nullopt); ASSERT_TRUE(cc); EXPECT_TRUE(this->SetCanonicalCookie( cs, std::move(cc), this->https_www_foo_.url(), true /*modify_httponly*/)); @@ -528,7 +528,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(one_hour_ago, it->LastAccessDate()); - EXPECT_FALSE(it->IsSecure()); + EXPECT_FALSE(it->SecureAttribute()); EXPECT_FALSE(it->IsHttpOnly()); ASSERT_TRUE(++it == cookies.end()); @@ -559,7 +559,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(one_hour_ago, it->LastAccessDate()); - EXPECT_FALSE(it->IsSecure()); + EXPECT_FALSE(it->SecureAttribute()); EXPECT_TRUE(it->IsHttpOnly()); EXPECT_TRUE(++it == cookies.end()); @@ -579,7 +579,7 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(it->CreationDate(), it->LastAccessDate()); - EXPECT_TRUE(it->IsSecure()); + EXPECT_TRUE(it->SecureAttribute()); EXPECT_FALSE(it->IsHttpOnly()); EXPECT_TRUE(++it == cookies.end()); @@ -629,9 +629,9 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { CookieInclusionStatus status; auto cookie = CanonicalCookie::Create( this->http_www_foo_.url(), "foo=1; Secure", base::Time::Now(), - /*server_time=*/absl::nullopt, /*cookie_partition_key=*/absl::nullopt, + /*server_time=*/std::nullopt, /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true, &status); - EXPECT_TRUE(cookie->IsSecure()); + EXPECT_TRUE(cookie->SecureAttribute()); EXPECT_TRUE(status.IsInclude()); EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult( cs, std::move(cookie), this->http_www_foo_.url(), true) @@ -679,8 +679,8 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { CookieInclusionStatus create_status; auto c = CanonicalCookie::Create(this->http_www_foo_.url(), "bar=1; HttpOnly", base::Time::Now(), - /*server_time=*/absl::nullopt, - /*cookie_partition_key=*/absl::nullopt, + /*server_time=*/std::nullopt, + /*cookie_partition_key=*/std::nullopt, /*block_truncated=*/true, &create_status); EXPECT_TRUE(c->IsHttpOnly()); EXPECT_TRUE(create_status.IsInclude()); @@ -741,7 +741,7 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(one_hour_ago, it->LastAccessDate()); - EXPECT_FALSE(it->IsSecure()); + EXPECT_FALSE(it->SecureAttribute()); EXPECT_FALSE(it->IsHttpOnly()); // Get the cookie using the wide open |options|: @@ -758,7 +758,7 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(one_hour_ago, it->LastAccessDate()); - EXPECT_FALSE(it->IsSecure()); + EXPECT_FALSE(it->SecureAttribute()); EXPECT_TRUE(it->IsHttpOnly()); cookies = this->GetAllCookiesForURL(cs, this->https_www_foo_.url()); @@ -776,7 +776,7 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) { // Some CookieStores don't store last access date. if (!it->LastAccessDate().is_null()) EXPECT_EQ(it->CreationDate(), it->LastAccessDate()); - EXPECT_TRUE(it->IsSecure()); + EXPECT_TRUE(it->SecureAttribute()); EXPECT_FALSE(it->IsHttpOnly()); } @@ -1313,8 +1313,8 @@ TYPED_TEST_P(CookieStoreTest, EmptyExpires) { this->MatchCookieLines(cookie_line, this->GetCookiesWithOptions(cs, url, options)); - absl::optional server_time = - absl::make_optional(base::Time::Now() - base::Hours(1)); + std::optional server_time = + std::make_optional(base::Time::Now() - base::Hours(1)); this->CreateAndSetCookie(cs, url, set_cookie_line, options, server_time); this->MatchCookieLines(cookie_line, this->GetCookiesWithOptions(cs, url, options)); diff --git a/naiveproxy/src/net/cookies/cookie_util.cc b/naiveproxy/src/net/cookies/cookie_util.cc index db5099ac3d..79f02586d5 100644 --- a/naiveproxy/src/net/cookies/cookie_util.cc +++ b/naiveproxy/src/net/cookies/cookie_util.cc @@ -138,7 +138,7 @@ ComputeContextRedirectTypeBug1221316(bool url_chain_is_length_one, ComputeSameSiteContextResult ComputeSameSiteContext( const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_http, bool is_main_frame_navigation, bool compute_schemefully) { @@ -254,7 +254,7 @@ void NormalizeStrictToLaxForSet(ComputeSameSiteContextResult& result) { CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet( const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_http, bool is_main_frame_navigation) { CookieOptions::SameSiteCookieContext same_site_context; @@ -283,22 +283,6 @@ void FireStorageAccessHistogram(StorageAccessResult result) { UMA_HISTOGRAM_ENUMERATION("API.StorageAccess.AllowedRequests2", result); } -void FireStorageAccessInputHistogram(bool has_opt_in, bool has_grant) { - StorageAccessInputState input_state; - if (has_opt_in && has_grant) { - input_state = StorageAccessInputState::kOptInWithGrant; - } else if (has_opt_in && !has_grant) { - input_state = StorageAccessInputState::kOptInWithoutGrant; - } else if (!has_opt_in && has_grant) { - input_state = StorageAccessInputState::kGrantWithoutOptIn; - } else if (!has_opt_in && !has_grant) { - input_state = StorageAccessInputState::kNoOptInNoGrant; - } else { - NOTREACHED_NORETURN(); - } - base::UmaHistogramEnumeration("API.StorageAccess.InputState", input_state); -} - bool DomainIsHostOnly(const std::string& domain_string) { return (domain_string.empty() || domain_string[0] != '.'); } @@ -701,7 +685,7 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest( const std::string& http_method, const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_main_frame_navigation, bool force_ignore_site_for_cookies) { // Set SameSiteCookieContext according to the rules laid out in @@ -768,7 +752,7 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest( NET_EXPORT CookieOptions::SameSiteCookieContext ComputeSameSiteContextForScriptGet(const GURL& url, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool force_ignore_site_for_cookies) { if (force_ignore_site_for_cookies) return CookieOptions::SameSiteCookieContext::MakeInclusive(); @@ -788,7 +772,7 @@ ComputeSameSiteContextForScriptGet(const GURL& url, CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse( const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_main_frame_navigation, bool force_ignore_site_for_cookies) { if (force_ignore_site_for_cookies) @@ -853,7 +837,7 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForScriptSet( // with the url. We don't check the redirect chain for script access to // cookies (only the URL itself). return ComputeSameSiteContextForSet( - {url}, site_for_cookies, absl::nullopt /* initiator */, + {url}, site_for_cookies, std::nullopt /* initiator */, false /* is_http */, false /* is_main_frame_navigation */); } @@ -899,7 +883,7 @@ bool IsSchemefulSameSiteEnabled() { return base::FeatureList::IsEnabled(features::kSchemefulSameSite); } -absl::optional< +std::optional< std::pair> ComputeFirstPartySetMetadataMaybeAsync( const SchemefulSite& request_site, @@ -915,8 +899,8 @@ ComputeFirstPartySetMetadataMaybeAsync( std::move(callback)); } - return std::make_pair(FirstPartySetMetadata(), - FirstPartySetsCacheFilter::MatchInfo()); + return std::pair(FirstPartySetMetadata(), + FirstPartySetsCacheFilter::MatchInfo()); } CookieOptions::SameSiteCookieContext::ContextMetadata::HttpMethod diff --git a/naiveproxy/src/net/cookies/cookie_util.h b/naiveproxy/src/net/cookies/cookie_util.h index 096ddb1b3c..ad7804641d 100644 --- a/naiveproxy/src/net/cookies/cookie_util.h +++ b/naiveproxy/src/net/cookies/cookie_util.h @@ -5,6 +5,7 @@ #ifndef NET_COOKIES_COOKIE_UTIL_H_ #define NET_COOKIES_COOKIE_UTIL_H_ +#include #include #include @@ -18,7 +19,6 @@ #include "net/cookies/site_for_cookies.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" class GURL; @@ -53,38 +53,11 @@ enum class StorageAccessResult { ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL = 9, kMaxValue = ACCESS_ALLOWED_TOP_LEVEL_3PCD_TRIAL, }; -// This enum must match the numbering for BreakageIndicatorType in -// histograms/enums.xml. Do not reorder or remove items, only add new items -// at the end. -enum class BreakageIndicatorType { - USER_RELOAD = 0, - HTTP_ERROR = 1, - UNCAUGHT_JS_ERROR = 2, - kMaxValue = UNCAUGHT_JS_ERROR, -}; + // Helper to fire telemetry indicating if a given request for storage was // allowed or not by the provided |result|. NET_EXPORT void FireStorageAccessHistogram(StorageAccessResult result); -// This enum must match the numbering for StorageAccessInputState in -// histograms/enums.xml. Do not reorder or remove items, only add new items at -// the end. -enum class StorageAccessInputState { - // The frame-level opt-in was provided, and a permission grant exists. - kOptInWithGrant = 0, - // The frame-level opt-in was provided, but no permission grant exists. - kOptInWithoutGrant = 1, - // No frame-level opt-in was provided, but a permission grant exists. - kGrantWithoutOptIn = 2, - // No frame-level opt-in was provided, and no permission grant exists. - kNoOptInNoGrant = 3, - kMaxValue = kNoOptInNoGrant, -}; -// Helper to record a histogram sample for relevant Storage Access API state -// when cookie settings queries consult the Storage Access API grants. -NET_EXPORT void FireStorageAccessInputHistogram(bool has_opt_in, - bool has_grant); - // Returns the effective TLD+1 for a given host. This only makes sense for http // and https schemes. For other schemes, the host will be returned unchanged // (minus any leading period). @@ -206,7 +179,7 @@ NET_EXPORT std::string SerializeRequestCookieLine( // `initiator` is the origin ultimately responsible for getting the request // issued. It may be different from `site_for_cookies`. // -// absl::nullopt for `initiator` denotes that the navigation was initiated by +// std::nullopt for `initiator` denotes that the navigation was initiated by // the user directly interacting with the browser UI, e.g. entering a URL // or selecting a bookmark. // @@ -231,7 +204,7 @@ NET_EXPORT CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest(const std::string& http_method, const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_main_frame_navigation, bool force_ignore_site_for_cookies); @@ -241,7 +214,7 @@ ComputeSameSiteContextForRequest(const std::string& http_method, NET_EXPORT CookieOptions::SameSiteCookieContext ComputeSameSiteContextForScriptGet(const GURL& url, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool force_ignore_site_for_cookies); // Determines which of the cookies for the request URL can be set from a network @@ -259,7 +232,7 @@ ComputeSameSiteContextForScriptGet(const GURL& url, NET_EXPORT CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse(const std::vector& url_chain, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, bool is_main_frame_navigation, bool force_ignore_site_for_cookies); @@ -298,7 +271,7 @@ NET_EXPORT bool IsSchemefulSameSiteEnabled(); // asynchronously with the result. The callback will be invoked iff the return // value is nullopt; i.e. a result will be provided via return value or // callback, but not both, and not neither. -[[nodiscard]] NET_EXPORT absl::optional< +[[nodiscard]] NET_EXPORT std::optional< std::pair> ComputeFirstPartySetMetadataMaybeAsync( const SchemefulSite& request_site, diff --git a/naiveproxy/src/net/cookies/test_cookie_access_delegate.cc b/naiveproxy/src/net/cookies/test_cookie_access_delegate.cc index efcd3c217d..b2081b5de0 100644 --- a/naiveproxy/src/net/cookies/test_cookie_access_delegate.cc +++ b/naiveproxy/src/net/cookies/test_cookie_access_delegate.cc @@ -59,7 +59,7 @@ bool TestCookieAccessDelegate::ShouldTreatUrlAsTrustworthy( return false; } -absl::optional< +std::optional< std::pair> TestCookieAccessDelegate::ComputeFirstPartySetMetadataMaybeAsync( const SchemefulSite& site, @@ -67,8 +67,8 @@ TestCookieAccessDelegate::ComputeFirstPartySetMetadataMaybeAsync( base::OnceCallback callback) const { - absl::optional top_frame_owner = - top_frame_site ? FindFirstPartySetEntry(*top_frame_site) : absl::nullopt; + std::optional top_frame_owner = + top_frame_site ? FindFirstPartySetEntry(*top_frame_site) : std::nullopt; FirstPartySetMetadata metadata( base::OptionalToPtr(FindFirstPartySetEntry(site)), base::OptionalToPtr(top_frame_owner)); @@ -79,28 +79,28 @@ TestCookieAccessDelegate::ComputeFirstPartySetMetadataMaybeAsync( base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(metadata), match_info)); - return absl::nullopt; + return std::nullopt; } - return std::make_pair(std::move(metadata), match_info); + return std::pair(std::move(metadata), match_info); } -absl::optional +std::optional TestCookieAccessDelegate::FindFirstPartySetEntry( const SchemefulSite& site) const { auto entry = first_party_sets_.find(site); - return entry != first_party_sets_.end() ? absl::make_optional(entry->second) - : absl::nullopt; + return entry != first_party_sets_.end() ? std::make_optional(entry->second) + : std::nullopt; } -absl::optional> +std::optional> TestCookieAccessDelegate::FindFirstPartySetEntries( const base::flat_set& sites, base::OnceCallback)> callback) const { std::vector> mapping; for (const SchemefulSite& site : sites) { - absl::optional entry = FindFirstPartySetEntry(site); + std::optional entry = FindFirstPartySetEntry(site); if (entry) mapping.emplace_back(site, *entry); } @@ -110,13 +110,13 @@ TestCookieAccessDelegate::FindFirstPartySetEntries( } template -absl::optional TestCookieAccessDelegate::RunMaybeAsync( +std::optional TestCookieAccessDelegate::RunMaybeAsync( T result, base::OnceCallback callback) const { if (invoke_callbacks_asynchronously_) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(result))); - return absl::nullopt; + return std::nullopt; } return result; } diff --git a/naiveproxy/src/net/cookies/test_cookie_access_delegate.h b/naiveproxy/src/net/cookies/test_cookie_access_delegate.h index 3f1ae960d9..7799c292f7 100644 --- a/naiveproxy/src/net/cookies/test_cookie_access_delegate.h +++ b/naiveproxy/src/net/cookies/test_cookie_access_delegate.h @@ -6,6 +6,7 @@ #define NET_COOKIES_TEST_COOKIE_ACCESS_DELEGATE_H_ #include +#include #include #include @@ -18,7 +19,6 @@ #include "net/first_party_sets/first_party_set_entry.h" #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_cache_filter.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -41,7 +41,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { const GURL& url, const SiteForCookies& site_for_cookies) const override; bool ShouldTreatUrlAsTrustworthy(const GURL& url) const override; - absl::optional< + std::optional< std::pair> ComputeFirstPartySetMetadataMaybeAsync( const SchemefulSite& site, @@ -49,7 +49,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { base::OnceCallback callback) const override; - absl::optional> + std::optional> FindFirstPartySetEntries( const base::flat_set& sites, base::OnceCallback< @@ -84,7 +84,7 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { private: // Finds a FirstPartySetEntry for the given site, if one exists. - absl::optional FindFirstPartySetEntry( + std::optional FindFirstPartySetEntry( const SchemefulSite& site) const; // Discard any leading dot in the domain string. @@ -93,8 +93,8 @@ class TestCookieAccessDelegate : public CookieAccessDelegate { // Invokes the given `callback` asynchronously or returns the result // synchronously, depending on the configuration of this instance. template - absl::optional RunMaybeAsync(T result, - base::OnceCallback callback) const; + std::optional RunMaybeAsync(T result, + base::OnceCallback callback) const; std::map expectations_; std::map ignore_samesite_restrictions_schemes_; diff --git a/naiveproxy/src/net/disk_cache/blockfile/block_files.cc b/naiveproxy/src/net/disk_cache/blockfile/block_files.cc index ebdf034bd2..f164cab028 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/block_files.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/block_files.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -17,7 +18,6 @@ #include "net/disk_cache/blockfile/file_lock.h" #include "net/disk_cache/blockfile/stress_support.h" #include "net/disk_cache/cache_util.h" -#include "third_party/abseil-cpp/absl/types/optional.h" using base::TimeTicks; @@ -350,7 +350,7 @@ void BlockFiles::DeleteBlock(Addr address, bool deep) { if (deep) file->Write(zero_buffer_.data(), size, offset); - absl::optional type_to_delete; + std::optional type_to_delete; { // Block Header can't outlive file's buffer. BlockHeader file_header(file); diff --git a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc index fc17b998c3..b70399fbef 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/entry_impl.cc @@ -759,17 +759,18 @@ std::string EntryImpl::GetKey() const { if (!key_file) return std::string(); - ++key_len; // We store a trailing \0 on disk. - if (!offset && key_file->GetLength() != static_cast(key_len)) + // We store a trailing \0 on disk. + if (!offset && key_file->GetLength() != static_cast(key_len + 1)) { return std::string(); + } - // WriteInto will ensure that key_.length() == key_len - 1, and so - // key_.c_str()[key_len] will be '\0'. Taking advantage of this, do not - // attempt read up to the expected on-disk '\0' --- which would be |key_len| - // bytes total --- as if due to a corrupt file it isn't |key_| would get its - // internal nul messed up. - if (!key_file->Read(base::WriteInto(&key_, key_len), key_len - 1, offset)) + // Do not attempt read up to the expected on-disk '\0' --- which would be + // |key_len + 1| bytes total --- as if due to a corrupt file it isn't |key_| + // would get its internal nul messed up. + key_.resize(key_len); + if (!key_file->Read(key_.data(), key_.size(), offset)) { key_.clear(); + } DCHECK_LE(strlen(key_.data()), static_cast(key_len)); return key_; } diff --git a/naiveproxy/src/net/disk_cache/blockfile/file_ios.cc b/naiveproxy/src/net/disk_cache/blockfile/file_ios.cc index e8cd3158a7..2fde5d5853 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/file_ios.cc +++ b/naiveproxy/src/net/disk_cache/blockfile/file_ios.cc @@ -13,6 +13,7 @@ #include "base/check.h" #include "base/functional/bind.h" #include "base/location.h" +#include "base/memory/raw_ptr.h" #include "base/task/thread_pool.h" #include "net/base/net_errors.h" #include "net/disk_cache/blockfile/in_flight_io.h" @@ -58,10 +59,10 @@ class FileBackgroundIO : public disk_cache::BackgroundIO { private: ~FileBackgroundIO() override {} - disk_cache::FileIOCallback* callback_; + raw_ptr callback_; - disk_cache::File* file_; - const void* buf_; + raw_ptr file_; + raw_ptr buf_; size_t buf_len_; size_t offset_; }; @@ -98,7 +99,7 @@ class FileInFlightIO : public disk_cache::InFlightIO { // Runs on a worker thread. void FileBackgroundIO::Read() { - if (file_->Read(const_cast(buf_), buf_len_, offset_)) { + if (file_->Read(const_cast(buf_.get()), buf_len_, offset_)) { result_ = static_cast(buf_len_); } else { result_ = net::ERR_CACHE_READ_FAILURE; diff --git a/naiveproxy/src/net/disk_cache/blockfile/storage_block-inl.h b/naiveproxy/src/net/disk_cache/blockfile/storage_block-inl.h index 161b81fa72..28d1d56425 100644 --- a/naiveproxy/src/net/disk_cache/blockfile/storage_block-inl.h +++ b/naiveproxy/src/net/disk_cache/blockfile/storage_block-inl.h @@ -12,6 +12,7 @@ #include +#include "base/containers/span.h" #include "base/hash/hash.h" #include "base/logging.h" #include "base/notreached.h" @@ -193,7 +194,8 @@ template void StorageBlock::DeleteData() { template uint32_t StorageBlock::CalculateHash() const { - return base::PersistentHash(data_, offsetof(T, self_hash)); + base::span bytes = base::as_bytes(base::span_from_ref(*data_)); + return base::PersistentHash(bytes.first(offsetof(T, self_hash))); } } // namespace disk_cache diff --git a/naiveproxy/src/net/disk_cache/cache_util.cc b/naiveproxy/src/net/disk_cache/cache_util.cc index e41fe434be..2a8a5be13d 100644 --- a/naiveproxy/src/net/disk_cache/cache_util.cc +++ b/naiveproxy/src/net/disk_cache/cache_util.cc @@ -59,7 +59,7 @@ base::FilePath GetTempCacheName(const base::FilePath& dirname, void CleanupTemporaryDirectories(const base::FilePath& path) { const base::FilePath dirname = path.DirName(); - const absl::optional basename = + const std::optional basename = base::SafeBaseName::Create(path); if (!basename.has_value()) { return; @@ -72,7 +72,7 @@ void CleanupTemporaryDirectories(const base::FilePath& path) { bool MoveDirectoryToTemporaryDirectory(const base::FilePath& path) { const base::FilePath dirname = path.DirName(); - const absl::optional basename = + const std::optional basename = base::SafeBaseName::Create(path); if (!basename.has_value()) { return false; diff --git a/naiveproxy/src/net/disk_cache/disk_cache.cc b/naiveproxy/src/net/disk_cache/disk_cache.cc index eb0f34b4e0..2becc408b0 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache.cc +++ b/naiveproxy/src/net/disk_cache/disk_cache.cc @@ -266,7 +266,7 @@ class TrivialFileEnumerator final : public FileEnumerator { : enumerator_(path) {} ~TrivialFileEnumerator() override = default; - absl::optional Next() override { + std::optional Next() override { return enumerator_.Next(); } bool HasError() const override { return enumerator_.HasError(); } @@ -601,7 +601,7 @@ bool TrivialFileOperations::ReplaceFile(const base::FilePath& from_path, return base::ReplaceFile(from_path, to_path, error); } -absl::optional TrivialFileOperations::GetFileInfo( +std::optional TrivialFileOperations::GetFileInfo( const base::FilePath& path) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(path.IsAbsolute()); @@ -611,7 +611,7 @@ absl::optional TrivialFileOperations::GetFileInfo( base::File::Info file_info; if (!base::GetFileInfo(path, &file_info)) { - return absl::nullopt; + return std::nullopt; } return file_info; } diff --git a/naiveproxy/src/net/disk_cache/disk_cache.h b/naiveproxy/src/net/disk_cache/disk_cache.h index cfeb141131..f6effa221d 100644 --- a/naiveproxy/src/net/disk_cache/disk_cache.h +++ b/naiveproxy/src/net/disk_cache/disk_cache.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -25,7 +26,6 @@ #include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/request_priority.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class FilePath; @@ -631,7 +631,7 @@ class BackendFileOperations { // Returns the next file in the directory, if any. Returns nullopt if there // are no further files (including the error case). The path of the // returned entry should be a full path. - virtual absl::optional Next() = 0; + virtual std::optional Next() = 0; // Returns true if we've found an error during traversal. virtual bool HasError() const = 0; @@ -662,7 +662,7 @@ class BackendFileOperations { base::File::Error* error) = 0; // Returns information about the given path. - virtual absl::optional GetFileInfo( + virtual std::optional GetFileInfo( const base::FilePath& path) = 0; // Creates an object that can be used to enumerate files in the specified @@ -729,7 +729,7 @@ class NET_EXPORT TrivialFileOperations final : public BackendFileOperations { bool ReplaceFile(const base::FilePath& from_path, const base::FilePath& to_path, base::File::Error* error) override; - absl::optional GetFileInfo( + std::optional GetFileInfo( const base::FilePath& path) override; std::unique_ptr EnumerateFiles( const base::FilePath& path) override; diff --git a/naiveproxy/src/net/disk_cache/simple/post_operation_waiter.cc b/naiveproxy/src/net/disk_cache/simple/post_operation_waiter.cc index e1b11502ef..945bfd98d1 100644 --- a/naiveproxy/src/net/disk_cache/simple/post_operation_waiter.cc +++ b/naiveproxy/src/net/disk_cache/simple/post_operation_waiter.cc @@ -15,8 +15,8 @@ SimplePostOperationWaiterTable::SimplePostOperationWaiterTable() = default; SimplePostOperationWaiterTable::~SimplePostOperationWaiterTable() = default; void SimplePostOperationWaiterTable::OnOperationStart(uint64_t entry_hash) { - auto [_, inserted] = entries_pending_operation_.insert( - std::make_pair(entry_hash, std::vector())); + auto [_, inserted] = entries_pending_operation_.emplace( + entry_hash, std::vector()); CHECK(inserted); } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc index 172694a8a0..5aa2fa1d9d 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_backend_impl.cc @@ -753,7 +753,7 @@ SimpleBackendImpl::DiskStatResult SimpleBackendImpl::InitCacheStructureOnDisk( << " path: " << path.LossyDisplayName(); result.net_error = net::ERR_FAILED; } else { - absl::optional file_info = + std::optional file_info = file_operations->GetFileInfo(path); if (!file_info.has_value()) { // Something deleted the directory between when we set it up and the diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc index 41ce42f3fa..64ea00c932 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include "net/disk_cache/simple/simple_util.h" #include "net/log/net_log.h" #include "net/log/net_log_source_type.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/zlib/zlib.h" namespace disk_cache { diff --git a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h index c7816fdff1..69e2a9ae91 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_entry_impl.h @@ -8,6 +8,7 @@ #include #include +#include #include #include "base/containers/queue.h" @@ -26,7 +27,6 @@ #include "net/disk_cache/simple/simple_synchronous_entry.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class TaskRunner; @@ -96,7 +96,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, // CompletionOnceCallback. net::Error DoomEntry(CompletionOnceCallback callback); - const absl::optional& key() const { return key_; } + const std::optional& key() const { return key_; } uint64_t entry_hash() const { return entry_hash_; } // The key is not a constructor parameter to the SimpleEntryImpl, because @@ -376,7 +376,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry, const base::FilePath path_; const uint64_t entry_hash_; const bool use_optimistic_operations_; - absl::optional key_; + std::optional key_; // |last_used_|, |last_modified_| and |data_size_| are copied from the // synchronous entry at the completion of each item of asynchronous IO. diff --git a/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.cc b/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.cc index 5ad2ad1a44..05cd9127a4 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.cc @@ -27,9 +27,9 @@ bool SimpleFileEnumerator::HasError() const { return has_error_; } -absl::optional SimpleFileEnumerator::Next() { +std::optional SimpleFileEnumerator::Next() { if (!dir_) { - return absl::nullopt; + return std::nullopt; } while (true) { // errno must be set to 0 before every readdir() call to detect errors. @@ -43,7 +43,7 @@ absl::optional SimpleFileEnumerator::Next() { PLOG(ERROR) << "readdir " << path_; has_error_ = true; dir_ = nullptr; - return absl::nullopt; + return std::nullopt; } break; } @@ -61,12 +61,12 @@ absl::optional SimpleFileEnumerator::Next() { if (file_info.is_directory) { continue; } - return absl::make_optional(std::move(path), file_info.size, - file_info.last_accessed, - file_info.last_modified); + return std::make_optional(std::move(path), file_info.size, + file_info.last_accessed, + file_info.last_modified); } dir_ = nullptr; - return absl::nullopt; + return std::nullopt; } #else @@ -80,15 +80,15 @@ bool SimpleFileEnumerator::HasError() const { return enumerator_.GetError() != base::File::FILE_OK; } -absl::optional SimpleFileEnumerator::Next() { +std::optional SimpleFileEnumerator::Next() { base::FilePath path = enumerator_.Next(); if (path.empty()) { - return absl::nullopt; + return std::nullopt; } base::FileEnumerator::FileInfo info = enumerator_.GetInfo(); - return absl::make_optional(std::move(path), info.GetSize(), - /*last_accessed=*/base::Time(), - info.GetLastModifiedTime()); + return std::make_optional(std::move(path), info.GetSize(), + /*last_accessed=*/base::Time(), + info.GetLastModifiedTime()); } #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.h b/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.h index 89d3760727..41dcf19b73 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_file_enumerator.h @@ -6,13 +6,13 @@ #define NET_DISK_CACHE_SIMPLE_SIMPLE_FILE_ENUMERATOR_H_ #include +#include #include "base/files/file_path.h" #include "base/time/time.h" #include "build/build_config.h" #include "net/base/net_export.h" #include "net/disk_cache/disk_cache.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #include @@ -38,7 +38,7 @@ class NET_EXPORT SimpleFileEnumerator final { // Returns the next item, or nullopt if there are no more results (including // the error case). - absl::optional Next(); + std::optional Next(); private: #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) diff --git a/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc b/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc index faf5e67fe1..b41ded573f 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_file_tracker.cc @@ -46,9 +46,9 @@ void SimpleFileTracker::Register(const SimpleSynchronousEntry* owner, base::AutoLock hold_lock(lock_); // Make sure the list of everything with given hash exists. - auto insert_status = tracked_files_.insert( - std::make_pair(owner->entry_file_key().entry_hash, - std::vector>())); + auto insert_status = + tracked_files_.emplace(owner->entry_file_key().entry_hash, + std::vector>()); std::vector>& candidates = insert_status.first->second; diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index.cc b/naiveproxy/src/net/disk_cache/simple/simple_index.cc index c3ea8e76bd..1adb727a1f 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_index.cc @@ -510,7 +510,7 @@ bool SimpleIndex::InsertInEntrySet( const disk_cache::EntryMetadata& entry_metadata, EntrySet* entry_set) { DCHECK(entry_set); - auto result = entry_set->insert(std::make_pair(entry_hash, entry_metadata)); + auto result = entry_set->emplace(entry_hash, entry_metadata); return result.second; } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_index_file.cc b/naiveproxy/src/net/disk_cache/simple/simple_index_file.cc index 4e6c6987a2..0188d8dea6 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_index_file.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_index_file.cc @@ -42,7 +42,7 @@ const int64_t kMaxIndexFileSizeBytes = kMaxEntriesInIndex * (8 + EntryMetadata::kOnDiskSizeBytes); uint32_t CalculatePickleCRC(const base::Pickle& pickle) { - return simple_util::Crc32(pickle.payload(), pickle.payload_size()); + return simple_util::Crc32(pickle.payload_bytes()); } // Used in histograms. Please only add new values at the end. @@ -309,7 +309,7 @@ void SimpleIndexFile::SyncWriteToDisk( // flush delay. This simple approach will be reconsidered if it does not allow // for maintaining freshness. base::Time cache_dir_mtime; - absl::optional file_info = + std::optional file_info = file_operations->GetFileInfo(cache_directory); if (!file_info) { LOG(ERROR) << "Could not obtain information about cache age"; @@ -605,7 +605,7 @@ void SimpleIndexFile::SyncRestoreFromDisk( SimpleIndex::EntrySet* entries = &out_result->entries; auto enumerator = file_operations->EnumerateFiles(cache_directory); - while (absl::optional entry = + while (std::optional entry = enumerator->Next()) { ProcessEntryFile(file_operations, cache_type, entries, entry->path, entry->last_accessed, entry->last_modified, entry->size); diff --git a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc index 3990b21a10..a0c620c31e 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.cc @@ -7,8 +7,10 @@ #include #include #include +#include #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/hash/hash.h" #include "base/location.h" @@ -33,7 +35,6 @@ #include "net/disk_cache/simple/simple_histogram_macros.h" #include "net/disk_cache/simple/simple_util.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/zlib/zlib.h" using base::FilePath; @@ -342,7 +343,7 @@ SimpleSynchronousEntry::SparseRequest::SparseRequest(int64_t sparse_offset_p, void SimpleSynchronousEntry::OpenEntry( net::CacheType cache_type, const FilePath& path, - const absl::optional& key, + const std::optional& key, const uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, @@ -1172,7 +1173,7 @@ void SimpleSynchronousEntry::Close( SimpleSynchronousEntry::SimpleSynchronousEntry( net::CacheType cache_type, const FilePath& path, - const absl::optional& key, + const std::optional& key, const uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr unbound_file_operations, @@ -1413,8 +1414,10 @@ bool SimpleSynchronousEntry::CheckHeaderAndKey(base::File* file, header = reinterpret_cast(header_data.data()); } - char* key_data = header_data.data() + sizeof(*header); - if (base::PersistentHash(key_data, header->key_length) != header->key_hash) { + const char* key_data = header_data.data() + sizeof(*header); + base::span key_span = + base::make_span(key_data, header->key_length); + if (base::PersistentHash(base::as_bytes(key_span)) != header->key_hash) { RecordSyncOpenResult(cache_type_, OPEN_ENTRY_KEY_HASH_MISMATCH); return false; } @@ -1984,7 +1987,7 @@ bool SimpleSynchronousEntry::ScanSparseFile(base::File* sparse_file, range.length = range_header.length; range.data_crc32 = range_header.data_crc32; range.file_offset = range_header_offset + sizeof(range_header); - sparse_ranges_.insert(std::make_pair(range.offset, range)); + sparse_ranges_.emplace(range.offset, range); range_header_offset += sizeof(range_header) + range.length; @@ -2105,7 +2108,7 @@ bool SimpleSynchronousEntry::AppendSparseRange(base::File* sparse_file, range.length = len; range.data_crc32 = data_crc32; range.file_offset = data_file_offset; - sparse_ranges_.insert(std::make_pair(offset, range)); + sparse_ranges_.emplace(offset, range); return true; } diff --git a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h index 0d24aa038b..e17377b21e 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_synchronous_entry.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include "net/disk_cache/simple/simple_entry_format.h" #include "net/disk_cache/simple/simple_file_tracker.h" #include "net/disk_cache/simple/simple_histogram_enums.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { class GrowableIOBuffer; @@ -191,7 +191,7 @@ class SimpleSynchronousEntry { NET_EXPORT_PRIVATE SimpleSynchronousEntry( net::CacheType cache_type, const base::FilePath& path, - const absl::optional& key, + const std::optional& key, uint64_t entry_hash, SimpleFileTracker* simple_file_tracker, std::unique_ptr file_operations, @@ -206,7 +206,7 @@ class SimpleSynchronousEntry { static void OpenEntry( net::CacheType cache_type, const base::FilePath& path, - const absl::optional& key, + const std::optional& key, uint64_t entry_hash, SimpleFileTracker* file_tracker, std::unique_ptr file_operations, @@ -305,7 +305,7 @@ class SimpleSynchronousEntry { SimpleEntryCloseResults* out_results); const base::FilePath& path() const { return path_; } - absl::optional key() const { return key_; } + std::optional key() const { return key_; } const SimpleFileTracker::EntryFileKey& entry_file_key() const { return entry_file_key_; } @@ -497,7 +497,7 @@ class SimpleSynchronousEntry { const net::CacheType cache_type_; const base::FilePath path_; SimpleFileTracker::EntryFileKey entry_file_key_; - absl::optional key_; + std::optional key_; bool have_open_files_ = false; bool initialized_ = false; diff --git a/naiveproxy/src/net/disk_cache/simple/simple_util.cc b/naiveproxy/src/net/disk_cache/simple/simple_util.cc index 369412a2eb..3832f58e73 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_util.cc +++ b/naiveproxy/src/net/disk_cache/simple/simple_util.cc @@ -104,6 +104,11 @@ int GetFileIndexFromStreamIndex(int stream_index) { return (stream_index == 2) ? 1 : 0; } +uint32_t Crc32(base::span data) { + auto chars = base::as_chars(data); + return Crc32(chars.data(), base::checked_cast(data.size())); +} + uint32_t Crc32(const char* data, int length) { uint32_t empty_crc = crc32(0, Z_NULL, 0); if (length == 0) diff --git a/naiveproxy/src/net/disk_cache/simple/simple_util.h b/naiveproxy/src/net/disk_cache/simple/simple_util.h index 5857e2bb98..f5a6327709 100644 --- a/naiveproxy/src/net/disk_cache/simple/simple_util.h +++ b/naiveproxy/src/net/disk_cache/simple/simple_util.h @@ -9,6 +9,7 @@ #include +#include "base/containers/span.h" #include "base/strings/string_piece.h" #include "net/base/net_export.h" #include "net/disk_cache/simple/simple_file_tracker.h" @@ -76,6 +77,8 @@ NET_EXPORT_PRIVATE int GetFileIndexFromStreamIndex(int stream_index); // file, it is possible to immediately create a new file with the same name. NET_EXPORT_PRIVATE bool SimpleCacheDeleteFile(const base::FilePath& path); +// Prefer span form for new code. +uint32_t Crc32(base::span data); uint32_t Crc32(const char* data, int length); uint32_t IncrementalCrc32(uint32_t previous_crc, const char* data, int length); diff --git a/naiveproxy/src/net/dns/context_host_resolver.cc b/naiveproxy/src/net/dns/context_host_resolver.cc index d56aa53782..82213f9e66 100644 --- a/naiveproxy/src/net/dns/context_host_resolver.cc +++ b/naiveproxy/src/net/dns/context_host_resolver.cc @@ -32,8 +32,8 @@ ContextHostResolver::ContextHostResolver( HostResolverManager* manager, std::unique_ptr resolve_context) : manager_(manager), resolve_context_(std::move(resolve_context)) { - DCHECK(manager_); - DCHECK(resolve_context_); + CHECK(manager_); + CHECK(resolve_context_); manager_->RegisterResolveContext(resolve_context_.get()); } @@ -58,11 +58,11 @@ ContextHostResolver::~ContextHostResolver() { void ContextHostResolver::OnShutdown() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(resolve_context_); + CHECK(resolve_context_); manager_->DeregisterResolveContext(resolve_context_.get()); resolve_context_.reset(); - DCHECK(!shutting_down_); + CHECK(!shutting_down_); shutting_down_ = true; } @@ -74,12 +74,12 @@ ContextHostResolver::CreateRequest( std::optional optional_parameters) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/1520189): `resolve_context_` should never be nullptr when - // `shutting_down_` is true. - if (shutting_down_ || !resolve_context_) { + if (shutting_down_) { return HostResolver::CreateFailingRequest(ERR_CONTEXT_SHUT_DOWN); } + CHECK(resolve_context_); + return manager_->CreateRequest( Host(std::move(host)), std::move(network_anonymization_key), std::move(source_net_log), std::move(optional_parameters), @@ -94,12 +94,12 @@ ContextHostResolver::CreateRequest( const std::optional& optional_parameters) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/1520189): `resolve_context_` should never be nullptr when - // `shutting_down_` is true. - if (shutting_down_ || !resolve_context_) { + if (shutting_down_) { return HostResolver::CreateFailingRequest(ERR_CONTEXT_SHUT_DOWN); } + CHECK(resolve_context_); + return manager_->CreateRequest(host, network_anonymization_key, source_net_log, optional_parameters, resolve_context_.get()); @@ -109,8 +109,11 @@ std::unique_ptr ContextHostResolver::CreateDohProbeRequest() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (shutting_down_) + if (shutting_down_) { return HostResolver::CreateFailingProbeRequest(ERR_CONTEXT_SHUT_DOWN); + } + + CHECK(resolve_context_); return manager_->CreateDohProbeRequest(resolve_context_.get()); } @@ -131,8 +134,8 @@ base::Value::Dict ContextHostResolver::GetDnsConfigAsValue() const { void ContextHostResolver::SetRequestContext( URLRequestContext* request_context) { - DCHECK(!shutting_down_); - DCHECK(resolve_context_); + CHECK(!shutting_down_); + CHECK(resolve_context_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); resolve_context_->set_url_request_context(request_context); diff --git a/naiveproxy/src/net/dns/dns_client.cc b/naiveproxy/src/net/dns/dns_client.cc index 16f32b43d6..f62a4bcdc7 100644 --- a/naiveproxy/src/net/dns/dns_client.cc +++ b/naiveproxy/src/net/dns/dns_client.cc @@ -10,6 +10,7 @@ #include #include "base/functional/bind.h" +#include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" @@ -240,6 +241,11 @@ class DnsClientImpl : public DnsClient { factory_ = std::move(factory); } + void SetAddressSorterForTesting( + std::unique_ptr address_sorter) override { + NOTIMPLEMENTED(); + } + private: std::optional BuildEffectiveConfig() const { DnsConfig config; diff --git a/naiveproxy/src/net/dns/dns_client.h b/naiveproxy/src/net/dns/dns_client.h index be4c98dda4..1632963d2b 100644 --- a/naiveproxy/src/net/dns/dns_client.h +++ b/naiveproxy/src/net/dns/dns_client.h @@ -111,6 +111,8 @@ class NET_EXPORT DnsClient { virtual void SetTransactionFactoryForTesting( std::unique_ptr factory) = 0; + virtual void SetAddressSorterForTesting( + std::unique_ptr address_sorter) = 0; // Creates default client. static std::unique_ptr CreateClient(NetLog* net_log); diff --git a/naiveproxy/src/net/dns/dns_config_service_linux.cc b/naiveproxy/src/net/dns/dns_config_service_linux.cc index 3c01e724ff..f909f127ba 100644 --- a/naiveproxy/src/net/dns/dns_config_service_linux.cc +++ b/naiveproxy/src/net/dns/dns_config_service_linux.cc @@ -375,7 +375,6 @@ class DnsConfigServiceLinux::Watcher : public DnsConfigService::Watcher { } void OnNsswitchFilePathWatcherChange(const base::FilePath& path, bool error) { - base::UmaHistogramBoolean("Net.DNS.DnsConfig.Nsswitch.FileChange", true); OnConfigChanged(!error); } diff --git a/naiveproxy/src/net/dns/dns_config_service_win.cc b/naiveproxy/src/net/dns/dns_config_service_win.cc index 2431d4629a..1d50a217ed 100644 --- a/naiveproxy/src/net/dns/dns_config_service_win.cc +++ b/naiveproxy/src/net/dns/dns_config_service_win.cc @@ -115,10 +115,10 @@ bool AddLocalhostEntriesTo(DnsHosts& in_out_hosts) { IPAddress loopback_ipv6 = IPAddress::IPv6Localhost(); // This does not override any pre-existing entries from the HOSTS file. - in_out_hosts.insert(std::make_pair( - DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4), loopback_ipv4)); - in_out_hosts.insert(std::make_pair( - DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6), loopback_ipv6)); + in_out_hosts.emplace(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV4), + loopback_ipv4); + in_out_hosts.emplace(DnsHostsKey("localhost", ADDRESS_FAMILY_IPV6), + loopback_ipv6); wchar_t buffer[MAX_PATH]; DWORD size = MAX_PATH; diff --git a/naiveproxy/src/net/dns/dns_test_util.cc b/naiveproxy/src/net/dns/dns_test_util.cc index 3d5af251c0..ee71d40476 100644 --- a/naiveproxy/src/net/dns/dns_test_util.cc +++ b/naiveproxy/src/net/dns/dns_test_util.cc @@ -176,13 +176,13 @@ std::pair BuildTestHttpsServiceAlpnParam( param_value.append(alpn); } - return std::make_pair(dns_protocol::kHttpsServiceParamKeyAlpn, - std::move(param_value)); + return std::pair(dns_protocol::kHttpsServiceParamKeyAlpn, + std::move(param_value)); } std::pair BuildTestHttpsServiceEchConfigParam( base::span ech_config_list) { - return std::make_pair( + return std::pair( dns_protocol::kHttpsServiceParamKeyEchConfig, std::string(reinterpret_cast(ech_config_list.data()), ech_config_list.size())); @@ -199,16 +199,16 @@ std::pair BuildTestHttpsServiceMandatoryParam( value.append(num_buffer, 2); } - return std::make_pair(dns_protocol::kHttpsServiceParamKeyMandatory, - std::move(value)); + return std::pair(dns_protocol::kHttpsServiceParamKeyMandatory, + std::move(value)); } std::pair BuildTestHttpsServicePortParam(uint16_t port) { char buffer[2]; base::WriteBigEndian(buffer, port); - return std::make_pair(dns_protocol::kHttpsServiceParamKeyPort, - std::string(buffer, 2)); + return std::pair(dns_protocol::kHttpsServiceParamKeyPort, + std::string(buffer, 2)); } DnsResourceRecord BuildTestHttpsServiceRecord( @@ -805,6 +805,11 @@ void MockDnsClient::SetTransactionFactoryForTesting( NOTREACHED(); } +void MockDnsClient::SetAddressSorterForTesting( + std::unique_ptr address_sorter) { + address_sorter_ = std::move(address_sorter); +} + std::optional> MockDnsClient::GetPresetAddrs( const url::SchemeHostPort& endpoint) const { EXPECT_THAT(preset_endpoint_, testing::Optional(endpoint)); diff --git a/naiveproxy/src/net/dns/dns_test_util.h b/naiveproxy/src/net/dns/dns_test_util.h index 6e946f2310..ed65181881 100644 --- a/naiveproxy/src/net/dns/dns_test_util.h +++ b/naiveproxy/src/net/dns/dns_test_util.h @@ -385,7 +385,8 @@ class MockDnsTransactionFactory : public DnsTransactionFactory { DelayedTransactionList delayed_transactions_; bool force_doh_server_available_ = true; - std::set running_doh_probe_runners_; + std::set> + running_doh_probe_runners_; base::WeakPtrFactory weak_ptr_factory_{this}; }; @@ -419,6 +420,8 @@ class MockDnsClient : public DnsClient { DnsConfigOverrides GetConfigOverridesForTesting() const override; void SetTransactionFactoryForTesting( std::unique_ptr factory) override; + void SetAddressSorterForTesting( + std::unique_ptr address_sorter) override; std::optional> GetPresetAddrs( const url::SchemeHostPort& endpoint) const override; diff --git a/naiveproxy/src/net/dns/host_cache.cc b/naiveproxy/src/net/dns/host_cache.cc index 2d63fc0201..c1a8f76389 100644 --- a/naiveproxy/src/net/dns/host_cache.cc +++ b/naiveproxy/src/net/dns/host_cache.cc @@ -138,9 +138,8 @@ EndpointMetadataPairFromValue(const base::Value& value) { if (!metadata) return std::nullopt; - return std::make_pair( - base::checked_cast(priority.value()), - std::move(metadata).value()); + return std::pair(base::checked_cast(priority.value()), + std::move(metadata).value()); } bool IPEndPointsFromLegacyAddressListValue( @@ -1179,16 +1178,6 @@ size_t HostCache::max_entries() const { return max_entries_; } -// static -std::unique_ptr HostCache::CreateDefaultCache() { -#if defined(ENABLE_BUILT_IN_DNS) - const size_t kDefaultMaxEntries = 1000; -#else - const size_t kDefaultMaxEntries = 100; -#endif - return std::make_unique(kDefaultMaxEntries); -} - bool HostCache::EvictOneEntry(base::TimeTicks now) { DCHECK_LT(0u, entries_.size()); diff --git a/naiveproxy/src/net/dns/host_cache.h b/naiveproxy/src/net/dns/host_cache.h index c3f97341f0..57b706fd57 100644 --- a/naiveproxy/src/net/dns/host_cache.h +++ b/naiveproxy/src/net/dns/host_cache.h @@ -476,9 +476,6 @@ class NET_EXPORT HostCache { int network_changes() const { return network_changes_; } const EntryMap& entries() const { return entries_; } - // Creates a default cache. - static std::unique_ptr CreateDefaultCache(); - private: FRIEND_TEST_ALL_PREFIXES(HostCacheTest, NoCache); diff --git a/naiveproxy/src/net/dns/host_resolver_dns_task.cc b/naiveproxy/src/net/dns/host_resolver_dns_task.cc index 658f361686..203d3c0a11 100644 --- a/naiveproxy/src/net/dns/host_resolver_dns_task.cc +++ b/naiveproxy/src/net/dns/host_resolver_dns_task.cc @@ -17,6 +17,7 @@ #include "net/dns/dns_transaction.h" #include "net/dns/dns_util.h" #include "net/dns/host_resolver.h" +#include "net/dns/host_resolver_cache.h" #include "net/dns/host_resolver_internal_result.h" #include "net/dns/public/util.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -134,6 +135,7 @@ bool HostResolverDnsTask::TransactionInfo::operator<( HostResolverDnsTask::HostResolverDnsTask( DnsClient* client, absl::variant host, + NetworkAnonymizationKey anonymization_key, DnsQueryTypeSet query_types, ResolveContext* resolve_context, bool secure, @@ -145,6 +147,7 @@ HostResolverDnsTask::HostResolverDnsTask( const HostResolver::HttpsSvcbOptions& https_svcb_options) : client_(client), host_(std::move(host)), + anonymization_key_(std::move(anonymization_key)), resolve_context_(resolve_context->AsSafeRef()), secure_(secure), secure_dns_mode_(secure_dns_mode), @@ -170,7 +173,7 @@ void HostResolverDnsTask::StartNextTransaction() { DCHECK_GE(num_additional_transactions_needed(), 1); if (!any_transaction_started_) { - net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK, + net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_DNS_TASK, [&] { return NetLogDnsTaskCreationParams(); }); } any_transaction_started_ = true; @@ -322,7 +325,7 @@ void HostResolverDnsTask::CreateAndStartTransaction( } void HostResolverDnsTask::OnTimeout() { - net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK_TIMEOUT, + net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_DNS_TASK_TIMEOUT, [&] { return NetLogDnsTaskTimeoutParams(); }); for (const TransactionInfo& transaction : transactions_in_progress_) { @@ -418,19 +421,22 @@ void HostResolverDnsTask::OnDnsTransactionComplete( DCHECK(response); - DnsResponseResultExtractor extractor(*response); - DnsResponseResultExtractor::ResultsOrError results = - extractor.ExtractDnsResults( - transaction_info.type, - /*original_domain_name=*/HostResolver::GetHostname(host_), - request_port); + DnsResponseResultExtractor::ResultsOrError results; + { + // Scope the extractor to ensure it is destroyed before `response`. + DnsResponseResultExtractor extractor(*response); + results = extractor.ExtractDnsResults( + transaction_info.type, + /*original_domain_name=*/HostResolver::GetHostname(host_), + request_port); + } + DCHECK_NE(results.error_or(DnsResponseResultExtractor::ExtractionError::kOk), DnsResponseResultExtractor::ExtractionError::kUnexpected); if (!results.has_value()) { net_log_.AddEvent( - NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK_EXTRACTION_FAILURE, - [&] { + NetLogEventType::HOST_RESOLVER_DNS_TASK_EXTRACTION_FAILURE, [&] { return NetLogDnsTaskExtractionFailureParams(results.error(), transaction_info.type); }); @@ -451,6 +457,17 @@ void HostResolverDnsTask::OnDnsTransactionComplete( } } CHECK(results.has_value()); + net_log_.AddEvent(NetLogEventType::HOST_RESOLVER_DNS_TASK_EXTRACTION_RESULTS, + [&] { + base::Value::List list; + list.reserve(results.value().size()); + for (const auto& result : results.value()) { + list.Append(result->ToValue()); + } + base::Value::Dict dict; + dict.Set("results", std::move(list)); + return dict; + }); if (httpssvc_metrics_) { if (transaction_info.type == DnsQueryType::HTTPS) { @@ -513,48 +530,13 @@ void HostResolverDnsTask::OnDnsTransactionComplete( break; } - // TODO(crbug.com/1381506): Use new results type directly instead of - // converting to HostCache::Entry. - HostCache::Entry legacy_results(std::move(results).value(), base::Time::Now(), - tick_clock_->NowTicks(), - HostCache::Entry::SOURCE_DNS); - - // Merge results with saved results from previous transactions. - if (saved_results_) { - // If saved result is a deferred failure, try again to complete with that - // failure. - if (saved_results_is_failure_) { - OnFailure(saved_results_.value().error(), /*allow_fallback=*/true, - saved_results_.value().GetOptionalTtl()); - return; - } - - switch (transaction_info.type) { - case DnsQueryType::A: - // Canonical names from A results have lower priority than those - // from AAAA results, so merge to the back. - legacy_results = HostCache::Entry::MergeEntries( - std::move(saved_results_).value(), std::move(legacy_results)); - break; - case DnsQueryType::AAAA: - // Canonical names from AAAA results take priority over those - // from A results, so merge to the front. - legacy_results = HostCache::Entry::MergeEntries( - std::move(legacy_results), std::move(saved_results_).value()); - break; - case DnsQueryType::HTTPS: - // No particular importance to order. - legacy_results = HostCache::Entry::MergeEntries( - std::move(legacy_results), std::move(saved_results_).value()); - break; - default: - // Only expect address query types with multiple transactions. - NOTREACHED(); - } + if (base::FeatureList::IsEnabled(features::kUseHostResolverCache)) { + SortTransactionAndHandleResults(std::move(transaction_info), + std::move(results).value()); + } else { + HandleTransactionResults(std::move(transaction_info), + std::move(results).value()); } - - saved_results_ = std::move(legacy_results); - OnTransactionsFinished(); } bool HostResolverDnsTask::IsFatalTransactionFailure( @@ -606,6 +588,171 @@ bool HostResolverDnsTask::IsFatalTransactionFailure( return error == HttpsTransactionError::kFatalErrorEnabled; } +void HostResolverDnsTask::SortTransactionAndHandleResults( + TransactionInfo transaction_info, + Results transaction_results) { + // Expect at most 1 data result in an individual transaction. + CHECK_LE(base::ranges::count_if( + transaction_results, + [](const std::unique_ptr& result) { + return result->type() == + HostResolverInternalResult::Type::kData; + }), + 1); + + auto data_result_it = base::ranges::find_if( + transaction_results, + [](const std::unique_ptr& result) { + return result->type() == HostResolverInternalResult::Type::kData; + }); + + std::vector endpoints_to_sort; + if (data_result_it != transaction_results.end()) { + const HostResolverInternalDataResult& data_result = + (*data_result_it)->AsData(); + endpoints_to_sort.insert(endpoints_to_sort.end(), + data_result.endpoints().begin(), + data_result.endpoints().end()); + } + + if (!endpoints_to_sort.empty()) { + // More async work to do, so insert `transaction_info` back onto + // `transactions_in_progress_`. + auto insertion_result = + transactions_in_progress_.insert(std::move(transaction_info)); + CHECK(insertion_result.second); + + // Sort() potentially calls OnTransactionSorted() synchronously. + client_->GetAddressSorter()->Sort( + endpoints_to_sort, + base::BindOnce(&HostResolverDnsTask::OnTransactionSorted, AsWeakPtr(), + insertion_result.first, std::move(transaction_results))); + } else { + HandleTransactionResults(std::move(transaction_info), + std::move(transaction_results)); + } +} + +void HostResolverDnsTask::OnTransactionSorted( + std::set::iterator transaction_info_it, + Results transaction_results, + bool success, + std::vector sorted) { + CHECK(transaction_info_it != transactions_in_progress_.end()); + + if (transactions_in_progress_.find(*transaction_info_it) == + transactions_in_progress_.end()) { + // If no longer in `transactions_in_progress_`, transaction was cancelled. + // Do nothing. + return; + } + TransactionInfo transaction_info = + std::move(transactions_in_progress_.extract(transaction_info_it).value()); + + if (!success) { + OnFailure( + ERR_DNS_SORT_ERROR, /*allow_fallback=*/true, + HostCache::Entry::TtlFromInternalResults( + transaction_results, base::Time::Now(), tick_clock_->NowTicks()), + transaction_info.type); + return; + } + + if (sorted.empty()) { + // Sorter prunes unusable destinations. If all addresses are pruned, + // remove the data result and replace with TTL-containing error result. + auto data_result_it = base::ranges::find_if( + transaction_results, + [](const std::unique_ptr& result) { + return result->type() == HostResolverInternalResult::Type::kData; + }); + CHECK(data_result_it != transaction_results.end()); + auto error_replacement = std::make_unique( + (*data_result_it)->domain_name(), (*data_result_it)->query_type(), + (*data_result_it)->expiration(), (*data_result_it)->timed_expiration(), + (*data_result_it)->source(), ERR_NAME_NOT_RESOLVED); + CHECK(error_replacement->expiration().has_value()); + CHECK(error_replacement->timed_expiration().has_value()); + + transaction_results.erase(data_result_it); + transaction_results.insert(std::move(error_replacement)); + } else { + bool replaced = false; // Should find exactly one data result to replace. + for (const std::unique_ptr& result : + transaction_results) { + if (result->type() == HostResolverInternalResult::Type::kData) { + CHECK(!replaced); + result->AsData().set_endpoints(std::move(sorted)); + replaced = true; + } + } + CHECK(replaced); + } + + HandleTransactionResults(std::move(transaction_info), + std::move(transaction_results)); +} + +void HostResolverDnsTask::HandleTransactionResults( + TransactionInfo transaction_info, + Results transaction_results) { + CHECK(transactions_in_progress_.find(transaction_info) == + transactions_in_progress_.end()); + + if (base::FeatureList::IsEnabled(features::kUseHostResolverCache) && + resolve_context_->host_resolver_cache() != nullptr) { + for (const std::unique_ptr& result : + transaction_results) { + resolve_context_->host_resolver_cache()->Set( + result->Clone(), anonymization_key_, HostResolverSource::DNS, + secure_); + } + } + + // TODO(crbug.com/1381506): Use new results type directly instead of + // converting to HostCache::Entry. + HostCache::Entry legacy_results(std::move(transaction_results), + base::Time::Now(), tick_clock_->NowTicks(), + HostCache::Entry::SOURCE_DNS); + + // Merge results with saved results from previous transactions. + if (saved_results_) { + // If saved result is a deferred failure, try again to complete with that + // failure. + if (saved_results_is_failure_) { + OnFailure(saved_results_.value().error(), /*allow_fallback=*/true, + saved_results_.value().GetOptionalTtl()); + return; + } + + switch (transaction_info.type) { + case DnsQueryType::A: + // Canonical names from A results have lower priority than those + // from AAAA results, so merge to the back. + legacy_results = HostCache::Entry::MergeEntries( + std::move(saved_results_).value(), std::move(legacy_results)); + break; + case DnsQueryType::AAAA: + // Canonical names from AAAA results take priority over those + // from A results, so merge to the front. + legacy_results = HostCache::Entry::MergeEntries( + std::move(legacy_results), std::move(saved_results_).value()); + break; + case DnsQueryType::HTTPS: + // No particular importance to order. + legacy_results = HostCache::Entry::MergeEntries( + std::move(legacy_results), std::move(saved_results_).value()); + break; + default: + // Only expect address query types with multiple transactions. + NOTREACHED(); + } + } + + saved_results_ = std::move(legacy_results); + OnTransactionsFinished(); +} + void HostResolverDnsTask::OnTransactionsFinished() { if (!transactions_in_progress_.empty() || !transactions_needed_.empty()) { delegate_->OnIntermediateTransactionsComplete(); @@ -618,21 +765,25 @@ void HostResolverDnsTask::OnTransactionsFinished() { timeout_timer_.Stop(); - std::vector ip_endpoints = results.ip_endpoints(); + // If using HostResolverCache, transactions are already invidvidually sorted + // on completion. + if (!base::FeatureList::IsEnabled(features::kUseHostResolverCache)) { + std::vector ip_endpoints = results.ip_endpoints(); - // If there are multiple addresses, and at least one is IPv6, need to - // sort them. - bool at_least_one_ipv6_address = base::ranges::any_of( - ip_endpoints, - [](auto& e) { return e.GetFamily() == ADDRESS_FAMILY_IPV6; }); - - if (at_least_one_ipv6_address) { - // Sort addresses if needed. Sort could complete synchronously. - client_->GetAddressSorter()->Sort( + // If there are multiple addresses, and at least one is IPv6, need to + // sort them. + bool at_least_one_ipv6_address = base::ranges::any_of( ip_endpoints, - base::BindOnce(&HostResolverDnsTask::OnSortComplete, AsWeakPtr(), - tick_clock_->NowTicks(), std::move(results), secure_)); - return; + [](auto& e) { return e.GetFamily() == ADDRESS_FAMILY_IPV6; }); + + if (at_least_one_ipv6_address) { + // Sort addresses if needed. Sort could complete synchronously. + client_->GetAddressSorter()->Sort( + ip_endpoints, + base::BindOnce(&HostResolverDnsTask::OnSortComplete, AsWeakPtr(), + tick_clock_->NowTicks(), std::move(results), secure_)); + return; + } } OnSuccess(std::move(results)); @@ -709,7 +860,7 @@ void HostResolverDnsTask::OnFailure( return; } - net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK, [&] { + net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_DNS_TASK, [&] { return NetLogDnsTaskFailedParams(net_error, failed_transaction_type, ttl, base::OptionalToPtr(saved_results_)); }); @@ -721,7 +872,7 @@ void HostResolverDnsTask::OnFailure( } void HostResolverDnsTask::OnSuccess(HostCache::Entry results) { - net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_MANAGER_DNS_TASK, + net_log_.EndEvent(NetLogEventType::HOST_RESOLVER_DNS_TASK, [&] { return NetLogResults(results); }); delegate_->OnDnsTaskComplete(task_start_time_, /*allow_fallback=*/true, std::move(results), secure_); diff --git a/naiveproxy/src/net/dns/host_resolver_dns_task.h b/naiveproxy/src/net/dns/host_resolver_dns_task.h index 7055e90921..0c19757598 100644 --- a/naiveproxy/src/net/dns/host_resolver_dns_task.h +++ b/naiveproxy/src/net/dns/host_resolver_dns_task.h @@ -66,6 +66,7 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask HostResolverDnsTask(DnsClient* client, absl::variant host, + NetworkAnonymizationKey anonymization_key, DnsQueryTypeSet query_types, ResolveContext* resolve_context, bool secure, @@ -153,6 +154,16 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask const TransactionInfo& transaction_info, const DnsResponse* response); + void SortTransactionAndHandleResults(TransactionInfo transaction_info, + Results transaction_results); + void OnTransactionSorted( + std::set::iterator transaction_info_it, + Results transaction_results, + bool success, + std::vector sorted); + void HandleTransactionResults(TransactionInfo transaction_info, + Results transaction_results); + void OnTransactionsFinished(); void OnSortComplete(base::TimeTicks sort_start_time, @@ -186,6 +197,7 @@ class NET_EXPORT_PRIVATE HostResolverDnsTask const raw_ptr client_; absl::variant host_; + NetworkAnonymizationKey anonymization_key_; base::SafeRef resolve_context_; diff --git a/naiveproxy/src/net/dns/host_resolver_internal_result.cc b/naiveproxy/src/net/dns/host_resolver_internal_result.cc index 59d5b15404..1b5b14e54b 100644 --- a/naiveproxy/src/net/dns/host_resolver_internal_result.cc +++ b/naiveproxy/src/net/dns/host_resolver_internal_result.cc @@ -92,8 +92,8 @@ EndpointMetadataPairFromValue(const base::Value& value) { if (!metadata) return std::nullopt; - return std::make_pair(base::checked_cast(weight.value()), - std::move(metadata).value()); + return std::pair(base::checked_cast(weight.value()), + std::move(metadata).value()); } std::optional QueryTypeFromValue(const base::Value& value) { @@ -203,24 +203,44 @@ const HostResolverInternalDataResult& HostResolverInternalResult::AsData() return *static_cast(this); } +HostResolverInternalDataResult& HostResolverInternalResult::AsData() { + CHECK_EQ(type_, Type::kData); + return *static_cast(this); +} + const HostResolverInternalMetadataResult& HostResolverInternalResult::AsMetadata() const { CHECK_EQ(type_, Type::kMetadata); return *static_cast(this); } +HostResolverInternalMetadataResult& HostResolverInternalResult::AsMetadata() { + CHECK_EQ(type_, Type::kMetadata); + return *static_cast(this); +} + const HostResolverInternalErrorResult& HostResolverInternalResult::AsError() const { CHECK_EQ(type_, Type::kError); return *static_cast(this); } +HostResolverInternalErrorResult& HostResolverInternalResult::AsError() { + CHECK_EQ(type_, Type::kError); + return *static_cast(this); +} + const HostResolverInternalAliasResult& HostResolverInternalResult::AsAlias() const { CHECK_EQ(type_, Type::kAlias); return *static_cast(this); } +HostResolverInternalAliasResult& HostResolverInternalResult::AsAlias() { + CHECK_EQ(type_, Type::kAlias); + return *static_cast(this); +} + HostResolverInternalResult::HostResolverInternalResult( std::string domain_name, DnsQueryType query_type, @@ -390,6 +410,14 @@ HostResolverInternalDataResult::HostResolverInternalDataResult( HostResolverInternalDataResult::~HostResolverInternalDataResult() = default; +std::unique_ptr +HostResolverInternalDataResult::Clone() const { + CHECK(timed_expiration().has_value()); + return std::make_unique( + domain_name(), query_type(), expiration(), timed_expiration().value(), + source(), endpoints(), strings(), hosts()); +} + base::Value HostResolverInternalDataResult::ToValue() const { base::Value::Dict dict = ToValueBaseDict(); @@ -470,6 +498,14 @@ HostResolverInternalMetadataResult::HostResolverInternalMetadataResult( HostResolverInternalMetadataResult::~HostResolverInternalMetadataResult() = default; +std::unique_ptr +HostResolverInternalMetadataResult::Clone() const { + CHECK(timed_expiration().has_value()); + return std::make_unique( + domain_name(), query_type(), expiration(), timed_expiration().value(), + source(), metadatas()); +} + base::Value HostResolverInternalMetadataResult::ToValue() const { base::Value::Dict dict = ToValueBaseDict(); @@ -522,6 +558,13 @@ HostResolverInternalErrorResult::HostResolverInternalErrorResult( source), error_(error) {} +std::unique_ptr +HostResolverInternalErrorResult::Clone() const { + return std::make_unique( + domain_name(), query_type(), expiration(), timed_expiration(), source(), + error()); +} + base::Value HostResolverInternalErrorResult::ToValue() const { base::Value::Dict dict = ToValueBaseDict(); @@ -569,6 +612,14 @@ HostResolverInternalAliasResult::HostResolverInternalAliasResult( DCHECK(!alias_target_.empty()); } +std::unique_ptr +HostResolverInternalAliasResult::Clone() const { + CHECK(timed_expiration().has_value()); + return std::make_unique( + domain_name(), query_type(), expiration(), timed_expiration().value(), + source(), alias_target()); +} + base::Value HostResolverInternalAliasResult::ToValue() const { base::Value::Dict dict = ToValueBaseDict(); diff --git a/naiveproxy/src/net/dns/host_resolver_internal_result.h b/naiveproxy/src/net/dns/host_resolver_internal_result.h index 30ce394bb3..89da833b6e 100644 --- a/naiveproxy/src/net/dns/host_resolver_internal_result.h +++ b/naiveproxy/src/net/dns/host_resolver_internal_result.h @@ -50,9 +50,15 @@ class NET_EXPORT_PRIVATE HostResolverInternalResult { } const HostResolverInternalDataResult& AsData() const; + HostResolverInternalDataResult& AsData(); const HostResolverInternalMetadataResult& AsMetadata() const; + HostResolverInternalMetadataResult& AsMetadata(); const HostResolverInternalErrorResult& AsError() const; + HostResolverInternalErrorResult& AsError(); const HostResolverInternalAliasResult& AsAlias() const; + HostResolverInternalAliasResult& AsAlias(); + + virtual std::unique_ptr Clone() const = 0; virtual base::Value ToValue() const = 0; @@ -121,8 +127,17 @@ class NET_EXPORT_PRIVATE HostResolverInternalDataResult final } const std::vector& endpoints() const { return endpoints_; } + void set_endpoints(std::vector endpoints) { + endpoints_ = std::move(endpoints); + } const std::vector& strings() const { return strings_; } + void set_strings(std::vector strings) { + strings_ = std::move(strings); + } const std::vector& hosts() const { return hosts_; } + void set_hosts(std::vector hosts) { hosts_ = std::move(hosts); } + + std::unique_ptr Clone() const override; base::Value ToValue() const override; @@ -134,13 +149,13 @@ class NET_EXPORT_PRIVATE HostResolverInternalDataResult final // Corresponds to the `HostResolverEndpointResult::ip_endpoints` portion of // `HostResolver::ResolveHostRequest::GetEndpointResults()`. - const std::vector endpoints_; + std::vector endpoints_; // Corresponds to `HostResolver::ResolveHostRequest::GetTextResults()`. - const std::vector strings_; + std::vector strings_; // Corresponds to `HostResolver::ResolveHostRequest::GetHostnameResults()`. - const std::vector hosts_; + std::vector hosts_; }; // Parsed and extracted connection metadata, but not usable on its own without @@ -179,6 +194,8 @@ class NET_EXPORT_PRIVATE HostResolverInternalMetadataResult final return metadatas_; } + std::unique_ptr Clone() const override; + base::Value ToValue() const override; private: @@ -218,6 +235,8 @@ class NET_EXPORT_PRIVATE HostResolverInternalErrorResult final int error() const { return error_; } + std::unique_ptr Clone() const override; + base::Value ToValue() const override; private: @@ -254,6 +273,8 @@ class NET_EXPORT_PRIVATE HostResolverInternalAliasResult final const std::string& alias_target() const { return alias_target_; } + std::unique_ptr Clone() const override; + base::Value ToValue() const override; private: diff --git a/naiveproxy/src/net/dns/host_resolver_manager_job.cc b/naiveproxy/src/net/dns/host_resolver_manager_job.cc index 35fd23995e..794d6be26e 100644 --- a/naiveproxy/src/net/dns/host_resolver_manager_job.cc +++ b/naiveproxy/src/net/dns/host_resolver_manager_job.cc @@ -641,9 +641,9 @@ void HostResolverManager::Job::StartDnsTask(bool secure) { // Need to create the task even if we're going to post a failure instead of // running it, as a "started" job needs a task to be properly cleaned up. dns_task_ = std::make_unique( - resolver_->dns_client_.get(), key_.host, key_.query_types, - &*key_.resolve_context, secure, key_.secure_dns_mode, this, net_log_, - tick_clock_, !tasks_.empty() /* fallback_available */, + resolver_->dns_client_.get(), key_.host, key_.network_anonymization_key, + key_.query_types, &*key_.resolve_context, secure, key_.secure_dns_mode, + this, net_log_, tick_clock_, !tasks_.empty() /* fallback_available */, https_svcb_options_); dns_task_->StartNextTransaction(); // Schedule a second transaction, if needed. DoH queries can bypass the diff --git a/naiveproxy/src/net/dns/mdns_cache.cc b/naiveproxy/src/net/dns/mdns_cache.cc index 0798525d17..cd46160d89 100644 --- a/naiveproxy/src/net/dns/mdns_cache.cc +++ b/naiveproxy/src/net/dns/mdns_cache.cc @@ -85,7 +85,7 @@ MDnsCache::UpdateType MDnsCache::UpdateDnsRecord( new_expiration = std::min(new_expiration, next_expiration_); std::pair insert_result = - mdns_cache_.insert(std::make_pair(cache_key, nullptr)); + mdns_cache_.emplace(cache_key, nullptr); UpdateType type = NoChange; if (insert_result.second) { type = RecordAdded; diff --git a/naiveproxy/src/net/dns/mdns_client.cc b/naiveproxy/src/net/dns/mdns_client.cc index 9e848e6fb8..407bcc58be 100644 --- a/naiveproxy/src/net/dns/mdns_client.cc +++ b/naiveproxy/src/net/dns/mdns_client.cc @@ -52,8 +52,7 @@ InterfaceIndexFamilyList GetMDnsInterfacesToBind() { for (const auto& network_interface : network_list) { AddressFamily family = GetAddressFamily(network_interface.address); if (family == ADDRESS_FAMILY_IPV4 || family == ADDRESS_FAMILY_IPV6) { - interfaces.push_back( - std::make_pair(network_interface.interface_index, family)); + interfaces.emplace_back(network_interface.interface_index, family); } } std::sort(interfaces.begin(), interfaces.end()); diff --git a/naiveproxy/src/net/dns/mdns_client_impl.cc b/naiveproxy/src/net/dns/mdns_client_impl.cc index e080ebc552..9fddefc231 100644 --- a/naiveproxy/src/net/dns/mdns_client_impl.cc +++ b/naiveproxy/src/net/dns/mdns_client_impl.cc @@ -143,7 +143,7 @@ void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { void MDnsConnection::SocketHandler::Send(const scoped_refptr& buffer, unsigned size) { if (send_in_progress_) { - send_queue_.push(std::make_pair(buffer, size)); + send_queue_.emplace(buffer, size); return; } int rv = @@ -317,7 +317,7 @@ void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, // Cleanup time may have changed. ScheduleCleanup(cache_.next_expiration()); - update_keys.insert(std::make_pair(update_key, update)); + update_keys.emplace(update_key, update); } for (const auto& update_key : update_keys) { diff --git a/naiveproxy/src/net/dns/mock_host_resolver.cc b/naiveproxy/src/net/dns/mock_host_resolver.cc index 8ea251be42..9e01a03ca4 100644 --- a/naiveproxy/src/net/dns/mock_host_resolver.cc +++ b/naiveproxy/src/net/dns/mock_host_resolver.cc @@ -841,7 +841,7 @@ void MockHostResolverBase::TriggerMdnsListeners( DnsQueryType query_type, MdnsListenerUpdateType update_type, const IPEndPoint& address_result) { - for (auto* listener : listeners_) { + for (MdnsListenerImpl* listener : listeners_) { if (listener->host() == host && listener->query_type() == query_type) listener->TriggerAddressResult(update_type, address_result); } @@ -852,7 +852,7 @@ void MockHostResolverBase::TriggerMdnsListeners( DnsQueryType query_type, MdnsListenerUpdateType update_type, const std::vector& text_result) { - for (auto* listener : listeners_) { + for (MdnsListenerImpl* listener : listeners_) { if (listener->host() == host && listener->query_type() == query_type) listener->TriggerTextResult(update_type, text_result); } @@ -863,7 +863,7 @@ void MockHostResolverBase::TriggerMdnsListeners( DnsQueryType query_type, MdnsListenerUpdateType update_type, const HostPortPair& host_result) { - for (auto* listener : listeners_) { + for (MdnsListenerImpl* listener : listeners_) { if (listener->host() == host && listener->query_type() == query_type) listener->TriggerHostnameResult(update_type, host_result); } @@ -873,7 +873,7 @@ void MockHostResolverBase::TriggerMdnsListeners( const HostPortPair& host, DnsQueryType query_type, MdnsListenerUpdateType update_type) { - for (auto* listener : listeners_) { + for (MdnsListenerImpl* listener : listeners_) { if (listener->host() == host && listener->query_type() == query_type) listener->TriggerUnhandledResult(update_type); } diff --git a/naiveproxy/src/net/dns/mock_host_resolver.h b/naiveproxy/src/net/dns/mock_host_resolver.h index 6d629917fa..db1774e355 100644 --- a/naiveproxy/src/net/dns/mock_host_resolver.h +++ b/naiveproxy/src/net/dns/mock_host_resolver.h @@ -443,7 +443,7 @@ class MockHostResolverBase const int initial_cache_invalidation_num_; std::map cache_invalidation_nums_; - std::set listeners_; + std::set> listeners_; size_t next_request_id_ = 1; diff --git a/naiveproxy/src/net/dns/mock_mdns_socket_factory.h b/naiveproxy/src/net/dns/mock_mdns_socket_factory.h index 7e5f721422..b746dad95a 100644 --- a/naiveproxy/src/net/dns/mock_mdns_socket_factory.h +++ b/naiveproxy/src/net/dns/mock_mdns_socket_factory.h @@ -48,7 +48,7 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket { MOCK_METHOD1(SetReceiveBufferSize, int(int32_t size)); MOCK_METHOD1(SetSendBufferSize, int(int32_t size)); MOCK_METHOD0(SetDoNotFragment, int()); - MOCK_METHOD0(SetRecvEcn, int()); + MOCK_METHOD0(SetRecvTos, int()); MOCK_METHOD1(SetMsgConfirm, void(bool confirm)); MOCK_METHOD0(Close, void()); @@ -70,8 +70,10 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket { MOCK_METHOD1(SetMulticastLoopbackMode, int(bool loopback)); MOCK_METHOD1(SetDiffServCodePoint, int(DiffServCodePoint dscp)); + MOCK_METHOD2(SetTos, int(DiffServCodePoint dscp, EcnCodePoint ecn)); MOCK_METHOD0(DetachFromThread, void()); + MOCK_CONST_METHOD0(GetLastTos, DscpAndEcn()); void SetResponsePacket(const std::string& response_packet); diff --git a/naiveproxy/src/net/dns/nsswitch_reader.cc b/naiveproxy/src/net/dns/nsswitch_reader.cc index e9966815b3..4af5ebc746 100644 --- a/naiveproxy/src/net/dns/nsswitch_reader.cc +++ b/naiveproxy/src/net/dns/nsswitch_reader.cc @@ -338,8 +338,6 @@ NsswitchReader::ReadAndParseHosts() { return GetDefaultHosts(); base::StringPiece hosts = FindDatabase(file, "hosts:"); - UMA_HISTOGRAM_BOOLEAN("Net.DNS.DnsConfig.Nsswitch.HostsFound", - !hosts.empty()); if (hosts.empty()) return GetDefaultHosts(); diff --git a/naiveproxy/src/net/dns/record_rdata.cc b/naiveproxy/src/net/dns/record_rdata.cc index 102591d96b..5d98b23758 100644 --- a/naiveproxy/src/net/dns/record_rdata.cc +++ b/naiveproxy/src/net/dns/record_rdata.cc @@ -66,9 +66,10 @@ std::unique_ptr SrvRecordRdata::Create( reader.ReadU16(&rdata->weight_); reader.ReadU16(&rdata->port_); - if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).begin(), - &rdata->target_)) + if (!parser.ReadName(data.substr(kSrvRecordMinimumSize).data(), + &rdata->target_)) { return nullptr; + } return rdata; } @@ -150,8 +151,9 @@ std::unique_ptr CnameRecordRdata::Create( const DnsRecordParser& parser) { auto rdata = base::WrapUnique(new CnameRecordRdata()); - if (!parser.ReadName(data.begin(), &rdata->cname_)) + if (!parser.ReadName(data.data(), &rdata->cname_)) { return nullptr; + } return rdata; } @@ -177,8 +179,9 @@ std::unique_ptr PtrRecordRdata::Create( const DnsRecordParser& parser) { auto rdata = base::WrapUnique(new PtrRecordRdata()); - if (!parser.ReadName(data.begin(), &rdata->ptrdomain_)) + if (!parser.ReadName(data.data(), &rdata->ptrdomain_)) { return nullptr; + } return rdata; } diff --git a/naiveproxy/src/net/dns/resolve_context.cc b/naiveproxy/src/net/dns/resolve_context.cc index 01b1d6a9a5..ac550f6ce0 100644 --- a/naiveproxy/src/net/dns/resolve_context.cc +++ b/naiveproxy/src/net/dns/resolve_context.cc @@ -28,6 +28,7 @@ #include "net/dns/dns_session.h" #include "net/dns/dns_util.h" #include "net/dns/host_cache.h" +#include "net/dns/host_resolver_cache.h" #include "net/dns/public/dns_over_https_config.h" #include "net/dns/public/doh_provider_entry.h" #include "net/dns/public/secure_dns_mode.h" @@ -117,6 +118,29 @@ static std::unique_ptr GetRttHistogram( return histogram; } +#if defined(ENABLE_BUILT_IN_DNS) +constexpr size_t kDefaultCacheSize = 1000; +#else +constexpr size_t kDefaultCacheSize = 100; +#endif + +std::unique_ptr CreateHostCache(bool enable_caching) { + if (enable_caching) { + return std::make_unique(kDefaultCacheSize); + } else { + return nullptr; + } +} + +std::unique_ptr CreateHostResolverCache( + bool enable_caching) { + if (enable_caching) { + return std::make_unique(kDefaultCacheSize); + } else { + return nullptr; + } +} + } // namespace ResolveContext::ServerStats::ServerStats( @@ -130,7 +154,8 @@ ResolveContext::ServerStats::~ServerStats() = default; ResolveContext::ResolveContext(URLRequestContext* url_request_context, bool enable_caching) : url_request_context_(url_request_context), - host_cache_(enable_caching ? HostCache::CreateDefaultCache() : nullptr), + host_cache_(CreateHostCache(enable_caching)), + host_resolver_cache_(CreateHostResolverCache(enable_caching)), isolation_info_(IsolationInfo::CreateTransient()) { max_fallback_period_ = GetMaxFallbackPeriod(); } diff --git a/naiveproxy/src/net/dns/resolve_context.h b/naiveproxy/src/net/dns/resolve_context.h index 31e21a63af..7cbbfd0cc1 100644 --- a/naiveproxy/src/net/dns/resolve_context.h +++ b/naiveproxy/src/net/dns/resolve_context.h @@ -30,6 +30,7 @@ class DnsSession; class DnsServerIterator; class DohDnsServerIterator; class HostCache; +class HostResolverCache; class URLRequestContext; // Represents various states of the DoH auto-upgrade process. @@ -180,6 +181,9 @@ class NET_EXPORT_PRIVATE ResolveContext : public base::CheckedObserver { } HostCache* host_cache() { return host_cache_.get(); } + HostResolverCache* host_resolver_cache() { + return host_resolver_cache_.get(); + } // Invalidate or clear saved per-context cached data that is not expected to // stay valid between connections or sessions (eg the HostCache and DNS server @@ -299,6 +303,7 @@ class NET_EXPORT_PRIVATE ResolveContext : public base::CheckedObserver { raw_ptr url_request_context_; std::unique_ptr host_cache_; + std::unique_ptr host_resolver_cache_; // Current maximum server fallback period. Updated on connection change. base::TimeDelta max_fallback_period_; diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.cc b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.cc index 73d9121475..fb1e8cb144 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.cc +++ b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.cc @@ -11,15 +11,19 @@ SharedDictionaryInfo::SharedDictionaryInfo( base::Time response_time, base::TimeDelta expiration, const std::string& match, + const std::string& match_dest_string, + const std::string& id, base::Time last_used_time, size_t size, const net::SHA256HashValue& hash, const base::UnguessableToken& disk_cache_key_token, - const absl::optional& primary_key_in_database) + const std::optional& primary_key_in_database) : url_(url), response_time_(response_time), expiration_(expiration), match_(match), + match_dest_string_(match_dest_string), + id_(id), last_used_time_(last_used_time), size_(size), hash_(hash), diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.h b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.h index 497bd07942..e846e6cca7 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.h +++ b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_info.h @@ -24,11 +24,13 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryInfo { base::Time response_time, base::TimeDelta expiration, const std::string& match, + const std::string& match_dest_string, + const std::string& id, base::Time last_used_time, size_t size, const net::SHA256HashValue& hash, const base::UnguessableToken& disk_cache_key_token, - const absl::optional& primary_key_in_database); + const std::optional& primary_key_in_database); SharedDictionaryInfo(const SharedDictionaryInfo&); SharedDictionaryInfo& operator=(const SharedDictionaryInfo&); @@ -44,6 +46,8 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryInfo { base::Time response_time() const { return response_time_; } base::TimeDelta expiration() const { return expiration_; } const std::string& match() const { return match_; } + const std::string& match_dest_string() const { return match_dest_string_; } + const std::string& id() const { return id_; } base::Time last_used_time() const { return last_used_time_; } size_t size() const { return size_; } const net::SHA256HashValue& hash() const { return hash_; } @@ -51,7 +55,7 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryInfo { return disk_cache_key_token_; } - const absl::optional& primary_key_in_database() const { + const std::optional& primary_key_in_database() const { return primary_key_in_database_; } void set_primary_key_in_database(int64_t primary_key_in_database) { @@ -76,6 +80,12 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryInfo { // The matching path pattern for the dictionary which was declared in // 'use-as-dictionary' response header's `match` option. std::string match_; + // The comma separated matching destinations for the dictionary which was + // declared in 'use-as-dictionary' response header's `match-dest` option. + std::string match_dest_string_; + // The Id for the dictionary which was declared in 'use-as-dictionary' + // response header's `id` option. + std::string id_; // The time when the dictionary was last used. base::Time last_used_time_; // The size of the dictionary binary. @@ -87,7 +97,7 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryInfo { base::UnguessableToken disk_cache_key_token_; // The primary key in SQLite database. This is nullopt until it is stored to // the database. - absl::optional primary_key_in_database_; + std::optional primary_key_in_database_; }; } // namespace net diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc index b0153d491d..a53e04a4d2 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc +++ b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.cc @@ -10,7 +10,7 @@ namespace net { // static -absl::optional +std::optional SharedDictionaryIsolationKey::MaybeCreate( const net::IsolationInfo& isolation_info) { if (!isolation_info.frame_origin() || @@ -18,7 +18,7 @@ SharedDictionaryIsolationKey::MaybeCreate( !isolation_info.top_frame_origin() || isolation_info.top_frame_origin()->opaque() || isolation_info.nonce().has_value()) { - return absl::nullopt; + return std::nullopt; } return SharedDictionaryIsolationKey( *isolation_info.frame_origin(), @@ -26,15 +26,15 @@ SharedDictionaryIsolationKey::MaybeCreate( } // static -absl::optional +std::optional SharedDictionaryIsolationKey::MaybeCreate( const NetworkIsolationKey& network_isolation_key, - const absl::optional& frame_origin) { + const std::optional& frame_origin) { if (!frame_origin || frame_origin->opaque() || !network_isolation_key.GetTopFrameSite() || network_isolation_key.GetTopFrameSite()->opaque() || network_isolation_key.GetNonce().has_value()) { - return absl::nullopt; + return std::nullopt; } return SharedDictionaryIsolationKey(*frame_origin, *network_isolation_key.GetTopFrameSite()); diff --git a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h index c817ab37ac..52421b6c66 100644 --- a/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h +++ b/naiveproxy/src/net/extras/shared_dictionary/shared_dictionary_isolation_key.h @@ -5,9 +5,10 @@ #ifndef NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ #define NET_EXTRAS_SHARED_DICTIONARY_SHARED_DICTIONARY_ISOLATION_KEY_H_ +#include + #include "base/component_export.h" #include "net/base/schemeful_site.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/origin.h" namespace net { @@ -20,15 +21,15 @@ class COMPONENT_EXPORT(NET_SHARED_DICTIONARY) SharedDictionaryIsolationKey { // Creates a SharedDictionaryIsolationKey. Returns nullopt when // `frame_origin` or `top_frame_origin` of `isolation_info` is not set or // opaque, or `nonce` is set. - static absl::optional MaybeCreate( + static std::optional MaybeCreate( const net::IsolationInfo& isolation_info); // Creates a SharedDictionaryIsolationKey. Returns nullopt when // `frame_origin` or `top_frame_origin` of `network_isolation_key` is not set // or opaque, or `nonce` of `network_isolation_key` is set. - static absl::optional MaybeCreate( + static std::optional MaybeCreate( const NetworkIsolationKey& network_isolation_key, - const absl::optional& frame_origin); + const std::optional& frame_origin); SharedDictionaryIsolationKey() = default; SharedDictionaryIsolationKey(const url::Origin& frame_origin, diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc index 0adc685726..b1ef939400 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_cookie_store.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,6 @@ #include "sql/meta_table.h" #include "sql/statement.h" #include "sql/transaction.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/third_party/mozilla/url_parse.h" @@ -115,15 +115,15 @@ namespace { // Version 19 - 2023/09/22 - https://crrev.com/c/4704672 // Version 18 - 2022/04/19 - https://crrev.com/c/3594203 // Version 17 - 2022/01/25 - https://crrev.com/c/3416230 -// Version 16 - 2021/09/10 - https://crrev.com/c/3152897 -// Version 15 - 2021/07/01 - https://crrev.com/c/3001822 // // Versions older than two years should be removed and marked as unsupported. -// This was last done August 1, 2023. https://crrev.com/c/4701765 +// This was last done in January 2024. https://crrev.com/c/5225715 // Be sure to update SQLitePersistentCookieStoreTest.TestInvalidVersionRecovery // to test the latest unsupported version number. // // Unsupported versions: +// Version 16 - 2021/09/10 - https://crrev.com/c/3152897 +// Version 15 - 2021/07/01 - https://crrev.com/c/3001822 // Version 14 - 2021/02/23 - https://crrev.com/c/2036899 // Version 13 - 2020/10/28 - https://crrev.com/c/2505468 // Version 12 - 2019/11/20 - https://crrev.com/c/1898301 @@ -315,7 +315,7 @@ class SQLitePersistentCookieStore::Backend } // Database upgrade statements. - absl::optional DoMigrateDatabaseSchema() override; + std::optional DoMigrateDatabaseSchema() override; class PendingOperation { public: @@ -532,80 +532,6 @@ class IncrementTimeDelta { base::Time start_; }; -// Initializes the cookies table, returning true on success. -// The table cannot exist when calling this function. -bool CreateV16Schema(sql::Database* db) { - DCHECK(!db->DoesTableExist("cookies")); - - std::string stmt(base::StringPrintf( - "CREATE TABLE cookies(" - "creation_utc INTEGER NOT NULL," - "top_frame_site_key TEXT NOT NULL," - "host_key TEXT NOT NULL," - "name TEXT NOT NULL," - "value TEXT NOT NULL," - "encrypted_value BLOB DEFAULT ''," - "path TEXT NOT NULL," - "expires_utc INTEGER NOT NULL," - "is_secure INTEGER NOT NULL," - "is_httponly INTEGER NOT NULL," - "last_access_utc INTEGER NOT NULL," - "has_expires INTEGER NOT NULL DEFAULT 1," - "is_persistent INTEGER NOT NULL DEFAULT 1," - "priority INTEGER NOT NULL DEFAULT %d," - "samesite INTEGER NOT NULL DEFAULT %d," - "source_scheme INTEGER NOT NULL DEFAULT %d," - "source_port INTEGER NOT NULL DEFAULT %d," - "is_same_party INTEGER NOT NULL DEFAULT 0," - "UNIQUE (top_frame_site_key, host_key, name, path))", - CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT), - CookieSameSiteToDBCookieSameSite(CookieSameSite::UNSPECIFIED), - static_cast(CookieSourceScheme::kUnset), - SQLitePersistentCookieStore::kDefaultUnknownPort)); - if (!db->Execute(stmt.c_str())) - return false; - - return true; -} - -// Initializes the cookies table, returning true on success. -// The table cannot exist when calling this function. -bool CreateV17Schema(sql::Database* db) { - DCHECK(!db->DoesTableExist("cookies")); - - const char* kCreateTableQuery = - "CREATE TABLE cookies(" - "creation_utc INTEGER NOT NULL," - "host_key TEXT NOT NULL," - "top_frame_site_key TEXT NOT NULL," - "name TEXT NOT NULL," - "value TEXT NOT NULL," - "encrypted_value BLOB NOT NULL," - "path TEXT NOT NULL," - "expires_utc INTEGER NOT NULL," - "is_secure INTEGER NOT NULL," - "is_httponly INTEGER NOT NULL," - "last_access_utc INTEGER NOT NULL," - "has_expires INTEGER NOT NULL," - "is_persistent INTEGER NOT NULL," - "priority INTEGER NOT NULL," - "samesite INTEGER NOT NULL," - "source_scheme INTEGER NOT NULL," - "source_port INTEGER NOT NULL," - "is_same_party INTEGER NOT NULL);"; - - const char* kCreateIndexQuery = - "CREATE UNIQUE INDEX cookies_unique_index " - "ON cookies(host_key, top_frame_site_key, name, path)"; - - if (!db->Execute(kCreateTableQuery)) - return false; - if (!db->Execute(kCreateIndexQuery)) - return false; - - return true; -} - // Initializes the cookies table, returning true on success. // The table cannot exist when calling this function. bool CreateV18Schema(sql::Database* db) { @@ -728,7 +654,7 @@ bool CreateV21Schema(sql::Database* db) { void SQLitePersistentCookieStore::Backend::Load( LoadedCallback loaded_callback) { - LoadCookiesForKey(absl::nullopt, std::move(loaded_callback)); + LoadCookiesForKey(std::nullopt, std::move(loaded_callback)); } void SQLitePersistentCookieStore::Backend::LoadCookiesForKey( @@ -965,7 +891,7 @@ bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement( value = statement.ColumnString(4); } - absl::optional cookie_partition_key; + std::optional cookie_partition_key; std::string top_frame_site_key = statement.ColumnString(2); // If we can't deserialize a top_frame_site_key, we delete any cookie with // that key. @@ -1019,105 +945,26 @@ bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement( return ok; } -absl::optional +std::optional SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { int cur_version = meta_table()->GetVersionNumber(); - if (cur_version == 15) { - sql::Transaction transaction(db()); - if (!transaction.Begin()) - return absl::nullopt; - - if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) - return absl::nullopt; - if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) - return absl::nullopt; - - if (!CreateV16Schema(db())) { - return absl::nullopt; - } - std::string insert_cookies_sql = base::StringPrintf( - "INSERT OR REPLACE INTO cookies " - "(creation_utc, host_key, top_frame_site_key, name, value, " - "encrypted_value, path, expires_utc, is_secure, is_httponly, " - "last_access_utc, has_expires, is_persistent, priority, samesite, " - "source_scheme, source_port, is_same_party) " - "SELECT creation_utc, host_key, top_frame_site_key, name, value," - " encrypted_value, path, expires_utc, is_secure, is_httponly," - " last_access_utc, has_expires, is_persistent, priority, " - "samesite," - " source_scheme, source_port, is_same_party " - "FROM cookies_old ORDER BY creation_utc ASC"); - if (!db()->Execute(insert_cookies_sql.c_str())) - return absl::nullopt; - if (!db()->Execute("DROP TABLE cookies_old")) - return absl::nullopt; - - ++cur_version; - if (!meta_table()->SetVersionNumber(cur_version) || - !meta_table()->SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)) || - !transaction.Commit()) { - return absl::nullopt; - } - } - - if (cur_version == 16) { - sql::Transaction transaction(db()); - if (!transaction.Begin()) - return absl::nullopt; - - if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) - return absl::nullopt; - if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) - return absl::nullopt; - if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) - return absl::nullopt; - - if (!CreateV17Schema(db())) - return absl::nullopt; - static constexpr char insert_cookies_sql[] = - "INSERT OR REPLACE INTO cookies " - "(creation_utc, host_key, top_frame_site_key, name, value, " - "encrypted_value, path, expires_utc, is_secure, is_httponly, " - "last_access_utc, has_expires, is_persistent, priority, samesite, " - "source_scheme, source_port, is_same_party) " - "SELECT creation_utc, host_key, top_frame_site_key, name, value," - " encrypted_value, path, expires_utc, is_secure, is_httponly," - " last_access_utc, has_expires, is_persistent, priority, " - "samesite," - " source_scheme, source_port, is_same_party " - "FROM cookies_old ORDER BY creation_utc ASC"; - if (!db()->Execute(insert_cookies_sql)) - return absl::nullopt; - if (!db()->Execute("DROP TABLE cookies_old")) - return absl::nullopt; - - ++cur_version; - if (!meta_table()->SetVersionNumber(cur_version) || - !meta_table()->SetCompatibleVersionNumber( - std::min(cur_version, kCompatibleVersionNumber)) || - !transaction.Commit()) { - return absl::nullopt; - } - } - if (cur_version == 17) { SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV18"); sql::Transaction transaction(db()); if (!transaction.Begin()) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) - return absl::nullopt; + return std::nullopt; if (!CreateV18Schema(db())) - return absl::nullopt; + return std::nullopt; static constexpr char insert_cookies_sql[] = "INSERT OR REPLACE INTO cookies " "(creation_utc, host_key, top_frame_site_key, name, value, " @@ -1130,16 +977,16 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { " samesite, source_scheme, source_port, is_same_party, 0 " "FROM cookies_old ORDER BY creation_utc ASC"; if (!db()->Execute(insert_cookies_sql)) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP TABLE cookies_old")) - return absl::nullopt; + return std::nullopt; ++cur_version; if (!meta_table()->SetVersionNumber(cur_version) || !meta_table()->SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)) || !transaction.Commit()) { - return absl::nullopt; + return std::nullopt; } } @@ -1151,19 +998,19 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { "UPDATE cookies SET expires_utc = ? WHERE " "has_expires = 1 AND expires_utc > ?")); if (!update_statement.is_valid()) { - return absl::nullopt; + return std::nullopt; } sql::Transaction transaction(db()); if (!transaction.Begin()) { - return absl::nullopt; + return std::nullopt; } base::Time expires_cap = base::Time::Now() + base::Days(400); update_statement.BindTime(0, expires_cap); update_statement.BindTime(1, expires_cap); if (!update_statement.Run()) { - return absl::nullopt; + return std::nullopt; } ++cur_version; @@ -1171,7 +1018,7 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { !meta_table()->SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)) || !transaction.Commit()) { - return absl::nullopt; + return std::nullopt; } } @@ -1180,21 +1027,21 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { sql::Transaction transaction(db()); if (!transaction.Begin()) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) { - return absl::nullopt; + return std::nullopt; } if (!CreateV20Schema(db())) { - return absl::nullopt; + return std::nullopt; } static constexpr char insert_cookies_sql[] = @@ -1210,10 +1057,10 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { "last_update_utc " "FROM cookies_old ORDER BY creation_utc ASC"; if (!db()->Execute(insert_cookies_sql)) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP TABLE cookies_old")) { - return absl::nullopt; + return std::nullopt; } ++cur_version; @@ -1221,7 +1068,7 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { !meta_table()->SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)) || !transaction.Commit()) { - return absl::nullopt; + return std::nullopt; } } @@ -1230,21 +1077,21 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { sql::Transaction transaction(db()); if (!transaction.Begin()) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP TABLE IF EXISTS cookies_old")) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old")) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP INDEX IF EXISTS cookies_unique_index")) { - return absl::nullopt; + return std::nullopt; } if (!CreateV21Schema(db())) { - return absl::nullopt; + return std::nullopt; } static constexpr char insert_cookies_sql[] = @@ -1259,10 +1106,10 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { " samesite, source_scheme, source_port, last_update_utc " "FROM cookies_old ORDER BY creation_utc ASC"; if (!db()->Execute(insert_cookies_sql)) { - return absl::nullopt; + return std::nullopt; } if (!db()->Execute("DROP TABLE cookies_old")) { - return absl::nullopt; + return std::nullopt; } ++cur_version; @@ -1270,13 +1117,13 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() { !meta_table()->SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)) || !transaction.Commit()) { - return absl::nullopt; + return std::nullopt; } } // Put future migration cases here. - return absl::make_optional(cur_version); + return std::make_optional(cur_version); } void SQLitePersistentCookieStore::Backend::AddCookie( @@ -1312,8 +1159,7 @@ void SQLitePersistentCookieStore::Backend::BatchOperation( // When queueing the operation, see if it overwrites any already pending // ones for the same row. auto key = cc.StrictlyUniqueKey(); - auto iter_and_result = - pending_.insert(std::make_pair(key, PendingOperationsForKey())); + auto iter_and_result = pending_.emplace(key, PendingOperationsForKey()); PendingOperationsForKey& ops_for_key = iter_and_result.first->second; if (!iter_and_result.second) { // Insert failed -> already have ops. @@ -1433,7 +1279,7 @@ void SQLitePersistentCookieStore::Backend::DoCommit() { } add_statement.BindString(6, po->cc().Path()); add_statement.BindTime(7, po->cc().ExpiryDate()); - add_statement.BindBool(8, po->cc().IsSecure()); + add_statement.BindBool(8, po->cc().SecureAttribute()); add_statement.BindBool(9, po->cc().IsHttpOnly()); add_statement.BindTime(10, po->cc().LastAccessDate()); add_statement.BindBool(11, po->cc().IsPersistent()); diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc index 08a7d63e71..95318ae0c4 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc @@ -79,7 +79,7 @@ base::TaskPriority GetReportingAndNelStoreBackgroundSequencePriority() { [[nodiscard]] bool NetworkAnonymizationKeyFromString( const std::string& string, NetworkAnonymizationKey* out_network_anonymization_key) { - absl::optional value = base::JSONReader::Read(string); + std::optional value = base::JSONReader::Read(string); if (!value) return false; @@ -188,7 +188,7 @@ class SQLitePersistentReportingAndNelStore::Backend // SQLitePersistentStoreBackendBase implementation bool CreateDatabaseSchema() override; - absl::optional DoMigrateDatabaseSchema() override; + std::optional DoMigrateDatabaseSchema() override; void DoCommit() override; // Commit a pending operation pertaining to a NEL policy. @@ -583,8 +583,7 @@ void SQLitePersistentReportingAndNelStore::Backend::AddReportingEndpoint( PendingOperationType::ADD, endpoint); if (!po) return; - ReportingEndpointKey key = - std::make_pair(endpoint.group_key, endpoint.info.url); + ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url); BatchOperation(std::move(key), std::move(po), &reporting_endpoint_pending_ops_); } @@ -616,8 +615,7 @@ void SQLitePersistentReportingAndNelStore::Backend:: PendingOperationType::UPDATE_DETAILS, endpoint); if (!po) return; - ReportingEndpointKey key = - std::make_pair(endpoint.group_key, endpoint.info.url); + ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url); BatchOperation(std::move(key), std::move(po), &reporting_endpoint_pending_ops_); } @@ -639,8 +637,7 @@ void SQLitePersistentReportingAndNelStore::Backend::DeleteReportingEndpoint( PendingOperationType::DELETE, endpoint); if (!po) return; - ReportingEndpointKey key = - std::make_pair(endpoint.group_key, endpoint.info.url); + ReportingEndpointKey key = std::pair(endpoint.group_key, endpoint.info.url); BatchOperation(std::move(key), std::move(po), &reporting_endpoint_pending_ops_); } @@ -694,7 +691,7 @@ bool SQLitePersistentReportingAndNelStore::Backend::CreateDatabaseSchema() { return true; } -absl::optional +std::optional SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() { int cur_version = meta_table()->GetVersionNumber(); @@ -709,15 +706,15 @@ SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() { if (cur_version == 1) { sql::Transaction transaction(db()); if (!transaction.Begin()) - return absl::nullopt; + return std::nullopt; // Migrate NEL policies table. if (!db()->Execute("DROP TABLE IF EXISTS nel_policies_old; " "ALTER TABLE nel_policies RENAME TO nel_policies_old")) { - return absl::nullopt; + return std::nullopt; } if (!CreateV2NelPoliciesSchema(db())) - return absl::nullopt; + return std::nullopt; // clang-format off // The "report_to" field is renamed to "group_name" for consistency with // the other tables. @@ -733,18 +730,18 @@ SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() { "FROM nel_policies_old" ; // clang-format on if (!db()->Execute(nel_policies_migrate_stmt.c_str())) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP TABLE nel_policies_old")) - return absl::nullopt; + return std::nullopt; // Migrate Reporting endpoints table. if (!db()->Execute("DROP TABLE IF EXISTS reporting_endpoints_old; " "ALTER TABLE reporting_endpoints RENAME TO " "reporting_endpoints_old")) { - return absl::nullopt; + return std::nullopt; } if (!CreateV2ReportingEndpointsSchema(db())) - return absl::nullopt; + return std::nullopt; // clang-format off std::string reporting_endpoints_migrate_stmt = "INSERT INTO reporting_endpoints (nik, origin_scheme, origin_host, " @@ -754,18 +751,18 @@ SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() { "FROM reporting_endpoints_old" ; // clang-format on if (!db()->Execute(reporting_endpoints_migrate_stmt.c_str())) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP TABLE reporting_endpoints_old")) - return absl::nullopt; + return std::nullopt; // Migrate Reporting endpoint groups table. if (!db()->Execute("DROP TABLE IF EXISTS reporting_endpoint_groups_old; " "ALTER TABLE reporting_endpoint_groups RENAME TO " "reporting_endpoint_groups_old")) { - return absl::nullopt; + return std::nullopt; } if (!CreateV2ReportingEndpointGroupsSchema(db())) - return absl::nullopt; + return std::nullopt; // clang-format off std::string reporting_endpoint_groups_migrate_stmt = "INSERT INTO reporting_endpoint_groups (nik, origin_scheme, " @@ -777,22 +774,22 @@ SQLitePersistentReportingAndNelStore::Backend::DoMigrateDatabaseSchema() { "FROM reporting_endpoint_groups_old" ; // clang-format on if (!db()->Execute(reporting_endpoint_groups_migrate_stmt.c_str())) - return absl::nullopt; + return std::nullopt; if (!db()->Execute("DROP TABLE reporting_endpoint_groups_old")) - return absl::nullopt; + return std::nullopt; ++cur_version; if (!meta_table()->SetVersionNumber(cur_version) || !meta_table()->SetCompatibleVersionNumber( std::min(cur_version, kCompatibleVersionNumber)) || !transaction.Commit()) { - return absl::nullopt; + return std::nullopt; } } // Future database upgrade statements go here. - return absl::make_optional(cur_version); + return std::make_optional(cur_version); } void SQLitePersistentReportingAndNelStore::Backend::DoCommit() { @@ -1178,8 +1175,8 @@ void SQLitePersistentReportingAndNelStore::Backend::BatchOperation( base::AutoLock locked(lock_); std::pair::iterator, bool> - iter_and_result = queue->insert(std::make_pair( - std::move(key), PendingOperationsVector())); + iter_and_result = + queue->emplace(std::move(key), PendingOperationsVector()); PendingOperationsVector* ops_for_key = &iter_and_result.first->second; // If the insert failed, then we already have operations for this diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc index 1e14dbdbbb..c54b648c46 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.cc @@ -34,20 +34,22 @@ constexpr char kTableName[] = "dictionaries"; // metadata because calculating the total size is an expensive operation. constexpr char kTotalDictSizeKey[] = "total_dict_size"; -const int kCurrentVersionNumber = 1; -const int kCompatibleVersionNumber = 1; +const int kCurrentVersionNumber = 2; +const int kCompatibleVersionNumber = 2; -bool CreateV1Schema(sql::Database* db, sql::MetaTable* meta_table) { +bool CreateV2Schema(sql::Database* db, sql::MetaTable* meta_table) { CHECK(!db->DoesTableExist(kTableName)); static constexpr char kCreateTableQuery[] = // clang-format off "CREATE TABLE dictionaries(" - "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + "primary_key INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," "frame_origin TEXT NOT NULL," "top_frame_site TEXT NOT NULL," "host TEXT NOT NULL," "match TEXT NOT NULL," + "match_dest TEXT NOT NULL," + "id TEXT NOT NULL," "url TEXT NOT NULL," "res_time INTEGER NOT NULL," "exp_time INTEGER NOT NULL," @@ -64,7 +66,8 @@ bool CreateV1Schema(sql::Database* db, sql::MetaTable* meta_table) { "frame_origin," "top_frame_site," "host," - "match)"; + "match," + "match_dest)"; // clang-format on // This index is used for the size and count limitation per top_frame_site. @@ -106,31 +109,32 @@ bool CreateV1Schema(sql::Database* db, sql::MetaTable* meta_table) { "last_used_time)"; // clang-format on - if (!db->Execute(kCreateTableQuery) || + sql::Transaction transaction(db); + if (!transaction.Begin() || !db->Execute(kCreateTableQuery) || !db->Execute(kCreateUniqueIndexQuery) || !db->Execute(kCreateTopFrameSiteIndexQuery) || !db->Execute(kCreateIsolationIndexQuery) || !db->Execute(kCreateTokenIndexQuery) || !db->Execute(kCreateExpirationTimeIndexQuery) || !db->Execute(kCreateLastUsedTimeIndexQuery) || - !meta_table->SetValue(kTotalDictSizeKey, 0)) { + !meta_table->SetValue(kTotalDictSizeKey, 0) || !transaction.Commit()) { return false; } return true; } -absl::optional ToSHA256HashValue( +std::optional ToSHA256HashValue( base::span sha256_bytes) { SHA256HashValue sha256_hash; if (sha256_bytes.size() != sizeof(sha256_hash.data)) { - return absl::nullopt; + return std::nullopt; } memcpy(sha256_hash.data, sha256_bytes.data(), sha256_bytes.size()); return sha256_hash; } -absl::optional ToUnguessableToken(int64_t token_high, - int64_t token_low) { +std::optional ToUnguessableToken(int64_t token_high, + int64_t token_low) { // There is no `sql::Statement::ColumnUint64()` method. So we cast to // uint64_t. return base::UnguessableToken::Deserialize(static_cast(token_high), @@ -174,7 +178,7 @@ void RecordErrorHistogram( SQLitePersistentSharedDictionaryStore::RegisterDictionaryResult:: RegisterDictionaryResult( int64_t primary_key_in_database, - absl::optional replaced_disk_cache_key_token, + std::optional replaced_disk_cache_key_token, std::set evicted_disk_cache_key_tokens, uint64_t total_dictionary_size, uint64_t total_dictionary_count) @@ -299,8 +303,9 @@ class SQLitePersistentSharedDictionaryStore::Backend const SharedDictionaryIsolationKey& isolation_key, const url::SchemeHostPort& host, const std::string& match, + const std::string& match_dest, int64_t* size_out, - absl::optional* disk_cache_key_out); + std::optional* disk_cache_key_out); // Updates the total dictionary size in MetaTable by `size_delta` and returns // the updated total dictionary size. @@ -313,7 +318,7 @@ class SQLitePersistentSharedDictionaryStore::Backend // SQLitePersistentStoreBackendBase implementation bool CreateDatabaseSchema() override; - absl::optional DoMigrateDatabaseSchema() override; + std::optional DoMigrateDatabaseSchema() override; void DoCommit() override; // Commits the last used time update. @@ -386,22 +391,36 @@ class SQLitePersistentSharedDictionaryStore::Backend bool SQLitePersistentSharedDictionaryStore::Backend::CreateDatabaseSchema() { if (!db()->DoesTableExist(kTableName) && - !CreateV1Schema(db(), meta_table())) { + !CreateV2Schema(db(), meta_table())) { return false; } return true; } -absl::optional +std::optional SQLitePersistentSharedDictionaryStore::Backend::DoMigrateDatabaseSchema() { int cur_version = meta_table()->GetVersionNumber(); - if (cur_version != kCurrentVersionNumber) { - return absl::nullopt; + if (cur_version == 1) { + sql::Transaction transaction(db()); + if (!transaction.Begin() || + !db()->Execute("DROP TABLE IF EXISTS dictionaries") || + !meta_table()->DeleteKey(kTotalDictSizeKey)) { + return std::nullopt; + } + // The version 1 is used during the Origin Trial period (M119-M122). + // We don't need to migrate the data from version 1. + ++cur_version; + if (!meta_table()->SetVersionNumber(cur_version) || + !meta_table()->SetCompatibleVersionNumber( + std::min(cur_version, kCompatibleVersionNumber)) || + !transaction.Commit()) { + return std::nullopt; + } } // Future database upgrade statements go here. - return absl::make_optional(cur_version); + return std::make_optional(cur_version); } void SQLitePersistentSharedDictionaryStore::Backend::DoCommit() { @@ -436,7 +455,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: return Error::kFailedToInitializeDatabase; } static constexpr char kQuery[] = - "UPDATE dictionaries SET last_used_time=? WHERE id=?"; + "UPDATE dictionaries SET last_used_time=? WHERE primary_key=?"; if (!db()->IsSQLValid(kQuery)) { return Error::kInvalidSql; @@ -493,12 +512,12 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( } int64_t size_of_removed_dict = 0; - absl::optional replaced_disk_cache_key_token; + std::optional replaced_disk_cache_key_token; int64_t size_delta = dictionary_info.size(); if (GetExistingDictionarySizeAndDiskCacheKeyToken( isolation_key, url::SchemeHostPort(dictionary_info.url()), - dictionary_info.match(), &size_of_removed_dict, - &replaced_disk_cache_key_token)) { + dictionary_info.match(), dictionary_info.match_dest_string(), + &size_of_removed_dict, &replaced_disk_cache_key_token)) { size_delta -= size_of_removed_dict; } @@ -509,6 +528,8 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( "top_frame_site," "host," "match," + "match_dest," + "id," "url," "res_time," "exp_time," @@ -517,7 +538,7 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( "sha256," "token_high," "token_low) " - "VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"; + "VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?)"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -530,24 +551,26 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( statement.BindString(2, url::SchemeHostPort(dictionary_info.url()).Serialize()); statement.BindString(3, dictionary_info.match()); - statement.BindString(4, dictionary_info.url().spec()); - statement.BindTime(5, dictionary_info.response_time()); - statement.BindTime(6, dictionary_info.GetExpirationTime()); - statement.BindTime(7, dictionary_info.last_used_time()); - statement.BindInt64(8, dictionary_info.size()); - statement.BindBlob(9, base::make_span(dictionary_info.hash().data)); + statement.BindString(4, dictionary_info.match_dest_string()); + statement.BindString(5, dictionary_info.id()); + statement.BindString(6, dictionary_info.url().spec()); + statement.BindTime(7, dictionary_info.response_time()); + statement.BindTime(8, dictionary_info.GetExpirationTime()); + statement.BindTime(9, dictionary_info.last_used_time()); + statement.BindInt64(10, dictionary_info.size()); + statement.BindBlob(11, base::make_span(dictionary_info.hash().data)); // There is no `sql::Statement::BindUint64()` method. So we cast to int64_t. int64_t token_high = static_cast( dictionary_info.disk_cache_key_token().GetHighForSerialization()); int64_t token_low = static_cast( dictionary_info.disk_cache_key_token().GetLowForSerialization()); - statement.BindInt64(10, token_high); - statement.BindInt64(11, token_low); + statement.BindInt64(12, token_high); + statement.BindInt64(13, token_low); if (!statement.Run()) { return base::unexpected(Error::kFailedToExecuteSql); } - int64_t id = db()->GetLastInsertRowId(); + int64_t primary_key = db()->GetLastInsertRowId(); uint64_t total_dictionary_size = 0; Error error = @@ -570,7 +593,7 @@ SQLitePersistentSharedDictionaryStore::Backend::RegisterDictionaryImpl( return base::unexpected(Error::kFailedToCommitTransaction); } return base::ok(RegisterDictionaryResult{ - id, replaced_disk_cache_key_token, + primary_key, replaced_disk_cache_key_token, std::set(evicted_disk_cache_key_tokens.begin(), evicted_disk_cache_key_tokens.end()), total_dictionary_size, total_dictionary_count}); @@ -652,7 +675,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "size," "token_high," "token_low FROM dictionaries " @@ -673,7 +696,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: const int64_t token_high = statement.ColumnInt64(2); const int64_t token_low = statement.ColumnInt64(3); - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -707,7 +730,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetDictionaryCountPerSite( static constexpr char kQuery[] = // clang-format off "SELECT " - "COUNT(id) FROM dictionaries " + "COUNT(primary_key) FROM dictionaries " "WHERE top_frame_site=?"; // clang-format on @@ -762,8 +785,10 @@ SQLitePersistentSharedDictionaryStore::Backend::GetDictionariesImpl( static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "match," + "match_dest," + "id," "url," "res_time," "exp_time," @@ -773,7 +798,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetDictionariesImpl( "token_high," "token_low FROM dictionaries " "WHERE frame_origin=? AND top_frame_site=? " - "ORDER BY id"; + "ORDER BY primary_key"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -787,28 +812,31 @@ SQLitePersistentSharedDictionaryStore::Backend::GetDictionariesImpl( while (statement.Step()) { const int64_t primary_key_in_database = statement.ColumnInt64(0); const std::string match = statement.ColumnString(1); - const std::string url_string = statement.ColumnString(2); - const base::Time response_time = statement.ColumnTime(3); - const base::Time expiration_time = statement.ColumnTime(4); - const base::Time last_used_time = statement.ColumnTime(5); - const size_t size = statement.ColumnInt64(6); + const std::string match_dest = statement.ColumnString(2); + const std::string id = statement.ColumnString(3); + const std::string url_string = statement.ColumnString(4); + const base::Time response_time = statement.ColumnTime(5); + const base::Time expiration_time = statement.ColumnTime(6); + const base::Time last_used_time = statement.ColumnTime(7); + const size_t size = statement.ColumnInt64(8); - absl::optional sha256_hash = - ToSHA256HashValue(statement.ColumnBlob(7)); + std::optional sha256_hash = + ToSHA256HashValue(statement.ColumnBlob(9)); if (!sha256_hash) { LOG(WARNING) << "Invalid hash"; continue; } - absl::optional disk_cache_key_token = - ToUnguessableToken(statement.ColumnInt64(8), statement.ColumnInt64(9)); + std::optional disk_cache_key_token = + ToUnguessableToken(statement.ColumnInt64(10), + statement.ColumnInt64(11)); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; continue; } result.emplace_back(GURL(url_string), response_time, - expiration_time - response_time, match, last_used_time, - size, *sha256_hash, *disk_cache_key_token, - primary_key_in_database); + expiration_time - response_time, match, match_dest, id, + last_used_time, size, *sha256_hash, + *disk_cache_key_token, primary_key_in_database); } return base::ok(std::move(result)); } @@ -823,10 +851,12 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDictionariesImpl() { static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "frame_origin," "top_frame_site," "match," + "match_dest," + "id," "url," "res_time," "exp_time," @@ -835,7 +865,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDictionariesImpl() { "sha256," "token_high," "token_low FROM dictionaries " - "ORDER BY id"; + "ORDER BY primary_key"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -851,22 +881,24 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDictionariesImpl() { const std::string frame_origin_string = statement.ColumnString(1); const std::string top_frame_site_string = statement.ColumnString(2); const std::string match = statement.ColumnString(3); - const std::string url_string = statement.ColumnString(4); - const base::Time response_time = statement.ColumnTime(5); - const base::Time expiration_time = statement.ColumnTime(6); - const base::Time last_used_time = statement.ColumnTime(7); - const size_t size = statement.ColumnInt64(8); + const std::string match_dest = statement.ColumnString(4); + const std::string id = statement.ColumnString(5); + const std::string url_string = statement.ColumnString(6); + const base::Time response_time = statement.ColumnTime(7); + const base::Time expiration_time = statement.ColumnTime(8); + const base::Time last_used_time = statement.ColumnTime(9); + const size_t size = statement.ColumnInt64(10); - absl::optional sha256_hash = - ToSHA256HashValue(statement.ColumnBlob(9)); + std::optional sha256_hash = + ToSHA256HashValue(statement.ColumnBlob(11)); if (!sha256_hash) { LOG(WARNING) << "Invalid hash"; continue; } - absl::optional disk_cache_key_token = - ToUnguessableToken(statement.ColumnInt64(10), - statement.ColumnInt64(11)); + std::optional disk_cache_key_token = + ToUnguessableToken(statement.ColumnInt64(12), + statement.ColumnInt64(13)); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; continue; @@ -877,8 +909,8 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDictionariesImpl() { result[SharedDictionaryIsolationKey(frame_origin, top_frame_site)] .emplace_back(GURL(url_string), response_time, - expiration_time - response_time, match, last_used_time, - size, *sha256_hash, *disk_cache_key_token, + expiration_time - response_time, match, match_dest, id, + last_used_time, size, *sha256_hash, *disk_cache_key_token, primary_key_in_database); } return base::ok(std::move(result)); @@ -897,7 +929,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetUsageInfoImpl() { "frame_origin," "top_frame_site," "size FROM dictionaries " - "ORDER BY id"; + "ORDER BY primary_key"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -945,7 +977,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetOriginsBetweenImpl( "SELECT " "frame_origin FROM dictionaries " "WHERE res_time>=? AND res_timeIsSQLValid(kQuery)) { @@ -988,7 +1020,7 @@ SQLitePersistentSharedDictionaryStore::Backend::ClearAllDictionariesImpl() { while (statement.Step()) { const int64_t token_high = statement.ColumnInt64(0); const int64_t token_low = statement.ColumnInt64(1); - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { continue; @@ -1067,12 +1099,12 @@ SQLitePersistentSharedDictionaryStore::Backend::SelectMatchingDictionaries( static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "size," "token_high," "token_low FROM dictionaries " "WHERE res_time>=? AND res_timeIsSQLValid(kQuery)) { @@ -1089,7 +1121,7 @@ SQLitePersistentSharedDictionaryStore::Backend::SelectMatchingDictionaries( const size_t size = statement.ColumnInt64(1); const int64_t token_high = statement.ColumnInt64(2); const int64_t token_low = statement.ColumnInt64(3); - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -1116,7 +1148,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "frame_origin," "top_frame_site," "host," @@ -1124,7 +1156,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: "token_high," "token_low FROM dictionaries " "WHERE res_time>=? AND res_timeIsSQLValid(kQuery)) { @@ -1150,7 +1182,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: !url_matcher.Run(GURL(host))) { continue; } - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -1201,7 +1233,7 @@ SQLitePersistentSharedDictionaryStore::Backend:: checked_total_size += size; - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { continue; @@ -1257,7 +1289,7 @@ SQLitePersistentSharedDictionaryStore::Backend::DeleteExpiredDictionariesImpl( checked_total_size += size; - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -1355,7 +1387,7 @@ SQLitePersistentSharedDictionaryStore::Backend::SelectEvictionCandidates( static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "size," "token_high," "token_low FROM dictionaries " @@ -1372,7 +1404,7 @@ SQLitePersistentSharedDictionaryStore::Backend::SelectEvictionCandidates( const size_t size = statement.ColumnInt64(1); const int64_t token_high = statement.ColumnInt64(2); const int64_t token_low = statement.ColumnInt64(3); - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(token_high, token_low); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -1403,7 +1435,8 @@ SQLitePersistentSharedDictionaryStore::Error SQLitePersistentSharedDictionaryStore::Backend::DeleteDictionaryByPrimaryKey( int64_t primary_key) { CHECK(background_task_runner()->RunsTasksInCurrentSequence()); - static constexpr char kQuery[] = "DELETE FROM dictionaries WHERE id=?"; + static constexpr char kQuery[] = + "DELETE FROM dictionaries WHERE primary_key=?"; if (!db()->IsSQLValid(kQuery)) { return Error::kInvalidSql; } @@ -1499,10 +1532,10 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDiskCacheKeyTokensImpl() { static constexpr char kQuery[] = // clang-format off "SELECT " - "id," + "primary_key," "token_high," "token_low FROM dictionaries " - "ORDER BY id"; + "ORDER BY primary_key"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -1512,7 +1545,7 @@ SQLitePersistentSharedDictionaryStore::Backend::GetAllDiskCacheKeyTokensImpl() { sql::Statement statement(db()->GetCachedStatement(SQL_FROM_HERE, kQuery)); std::vector tokens; while (statement.Step()) { - absl::optional disk_cache_key_token = + std::optional disk_cache_key_token = ToUnguessableToken(statement.ColumnInt64(1), statement.ColumnInt64(2)); if (!disk_cache_key_token) { LOG(WARNING) << "Invalid token"; @@ -1555,7 +1588,8 @@ void SQLitePersistentSharedDictionaryStore::Backend:: base::expected SQLitePersistentSharedDictionaryStore::Backend::GetTotalDictionaryCount() { CHECK(background_task_runner()->RunsTasksInCurrentSequence()); - static constexpr char kQuery[] = "SELECT COUNT(id) FROM dictionaries"; + static constexpr char kQuery[] = + "SELECT COUNT(primary_key) FROM dictionaries"; if (!db()->IsSQLValid(kQuery)) { return base::unexpected(Error::kInvalidSql); @@ -1573,8 +1607,9 @@ bool SQLitePersistentSharedDictionaryStore::Backend:: const SharedDictionaryIsolationKey& isolation_key, const url::SchemeHostPort& host, const std::string& match, + const std::string& match_dest, int64_t* size_out, - absl::optional* disk_cache_key_out) { + std::optional* disk_cache_key_out) { CHECK(background_task_runner()->RunsTasksInCurrentSequence()); static constexpr char kQuery[] = @@ -1583,8 +1618,13 @@ bool SQLitePersistentSharedDictionaryStore::Backend:: "size," "token_high," "token_low FROM dictionaries " - "WHERE frame_origin=? AND top_frame_site=? AND host=? AND match=? " - "ORDER BY id"; + "WHERE " + "frame_origin=? AND " + "top_frame_site=? AND " + "host=? AND " + "match=? AND " + "match_dest=? " + "ORDER BY primary_key"; // clang-format on if (!db()->IsSQLValid(kQuery)) { @@ -1595,6 +1635,7 @@ bool SQLitePersistentSharedDictionaryStore::Backend:: statement.BindString(1, isolation_key.top_frame_site().Serialize()); statement.BindString(2, host.Serialize()); statement.BindString(3, match); + statement.BindString(4, match_dest); if (statement.Step()) { *size_out = statement.ColumnInt64(0); diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.h b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.h index 364aa3edd8..b1bf1f1759 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.h +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_shared_dictionary_store.h @@ -53,7 +53,7 @@ class COMPONENT_EXPORT(NET_EXTRAS) SQLitePersistentSharedDictionaryStore { public: RegisterDictionaryResult( int64_t primary_key_in_database, - absl::optional replaced_disk_cache_key_token, + std::optional replaced_disk_cache_key_token, std::set evicted_disk_cache_key_tokens, uint64_t total_dictionary_size, uint64_t total_dictionary_count); @@ -65,8 +65,8 @@ class COMPONENT_EXPORT(NET_EXTRAS) SQLitePersistentSharedDictionaryStore { RegisterDictionaryResult& operator=(RegisterDictionaryResult&& other); int64_t primary_key_in_database() const { return primary_key_in_database_; } - const absl::optional& - replaced_disk_cache_key_token() const { + const std::optional& replaced_disk_cache_key_token() + const { return replaced_disk_cache_key_token_; } const std::set& evicted_disk_cache_key_tokens() @@ -78,7 +78,7 @@ class COMPONENT_EXPORT(NET_EXTRAS) SQLitePersistentSharedDictionaryStore { private: int64_t primary_key_in_database_; - absl::optional replaced_disk_cache_key_token_; + std::optional replaced_disk_cache_key_token_; std::set evicted_disk_cache_key_tokens_; uint64_t total_dictionary_size_; uint64_t total_dictionary_count_; diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc index 1bd6bbb31a..74213fb944 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.cc @@ -213,7 +213,7 @@ bool SQLitePersistentStoreBackendBase::MigrateDatabaseSchema() { // |cur_version| is the version that the database ends up at, after all the // database upgrade statements. - absl::optional cur_version = DoMigrateDatabaseSchema(); + std::optional cur_version = DoMigrateDatabaseSchema(); if (!cur_version.has_value()) return false; diff --git a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h index d8eb5431ea..0ace27e306 100644 --- a/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h +++ b/naiveproxy/src/net/extras/sqlite/sqlite_persistent_store_backend_base.h @@ -6,6 +6,7 @@ #define NET_EXTRAS_SQLITE_SQLITE_PERSISTENT_STORE_BACKEND_BASE_H_ #include +#include #include #include "base/files/file_path.h" @@ -14,7 +15,6 @@ #include "base/memory/ref_counted.h" #include "base/thread_annotations.h" #include "sql/meta_table.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class Location; @@ -96,9 +96,9 @@ class SQLitePersistentStoreBackendBase // Embedder-specific database upgrade statements. Returns the version number // that the database ends up at, or returns nullopt on error. This is called // during MigrateDatabaseSchema() which is called during InitializeDatabase(), - // and returning |absl::nullopt| will cause the initialization process to fail + // and returning |std::nullopt| will cause the initialization process to fail // and stop. - virtual absl::optional DoMigrateDatabaseSchema() = 0; + virtual std::optional DoMigrateDatabaseSchema() = 0; // Initializes the desired table(s) of the database, e.g. by creating them or // checking that they already exist. Returns whether the tables exist. diff --git a/naiveproxy/src/net/filter/zstd_source_stream.cc b/naiveproxy/src/net/filter/zstd_source_stream.cc index 551729ac54..4b6772f01b 100644 --- a/naiveproxy/src/net/filter/zstd_source_stream.cc +++ b/naiveproxy/src/net/filter/zstd_source_stream.cc @@ -98,7 +98,7 @@ class ZstdSourceStream : public FilterSourceStream { void* customMalloc(size_t size) { void* address = malloc(size); CHECK(address); - malloc_sizes_.insert(std::make_pair(address, size)); + malloc_sizes_.emplace(address, size); total_allocated_ += size; if (total_allocated_ > max_allocated_) { max_allocated_ = total_allocated_; @@ -143,6 +143,10 @@ class ZstdSourceStream : public FilterSourceStream { if (ZSTD_isError(result)) { decoding_status_ = ZstdDecodingStatus::kDecodingError; + if (ZSTD_getErrorCode(result) == + ZSTD_error_frameParameter_windowTooLarge) { + return base::unexpected(ERR_ZSTD_WINDOW_SIZE_TOO_BIG); + } return base::unexpected(ERR_CONTENT_DECODING_FAILED); } else if (input.pos < input.size) { // Given a valid frame, zstd won't consume the last byte of the frame diff --git a/naiveproxy/src/net/first_party_sets/first_party_set_entry.cc b/naiveproxy/src/net/first_party_sets/first_party_set_entry.cc index 8feda59a82..142c4e72fb 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_set_entry.cc +++ b/naiveproxy/src/net/first_party_sets/first_party_set_entry.cc @@ -39,7 +39,7 @@ FirstPartySetEntry::FirstPartySetEntry() = default; FirstPartySetEntry::FirstPartySetEntry( SchemefulSite primary, SiteType site_type, - absl::optional site_index) + std::optional site_index) : primary_(primary), site_type_(site_type), site_index_(site_index) { switch (site_type_) { case SiteType::kPrimary: @@ -57,7 +57,7 @@ FirstPartySetEntry::FirstPartySetEntry(SchemefulSite primary, : FirstPartySetEntry( primary, site_type, - absl::make_optional(FirstPartySetEntry::SiteIndex(site_index))) {} + std::make_optional(FirstPartySetEntry::SiteIndex(site_index))) {} FirstPartySetEntry::FirstPartySetEntry(const FirstPartySetEntry&) = default; FirstPartySetEntry& FirstPartySetEntry::operator=(const FirstPartySetEntry&) = @@ -75,7 +75,7 @@ bool FirstPartySetEntry::operator!=(const FirstPartySetEntry& other) const = default; // static -absl::optional FirstPartySetEntry::DeserializeSiteType( +std::optional FirstPartySetEntry::DeserializeSiteType( int value) { switch (value) { case static_cast(net::SiteType::kPrimary): @@ -87,7 +87,7 @@ absl::optional FirstPartySetEntry::DeserializeSiteType( default: NOTREACHED() << "Unknown SiteType: " << value; } - return absl::nullopt; + return std::nullopt; } std::string FirstPartySetEntry::GetDebugString() const { diff --git a/naiveproxy/src/net/first_party_sets/first_party_set_entry.h b/naiveproxy/src/net/first_party_sets/first_party_set_entry.h index a01955ea85..c626a40cec 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_set_entry.h +++ b/naiveproxy/src/net/first_party_sets/first_party_set_entry.h @@ -48,7 +48,7 @@ class NET_EXPORT FirstPartySetEntry { // entry. FirstPartySetEntry(SchemefulSite primary, SiteType site_type, - absl::optional site_index); + std::optional site_index); FirstPartySetEntry(SchemefulSite primary, SiteType site_type, uint32_t site_index); @@ -63,7 +63,7 @@ class NET_EXPORT FirstPartySetEntry { bool operator==(const FirstPartySetEntry& other) const; bool operator!=(const FirstPartySetEntry& other) const; - static absl::optional DeserializeSiteType(int value); + static std::optional DeserializeSiteType(int value); std::string GetDebugString() const; @@ -71,7 +71,7 @@ class NET_EXPORT FirstPartySetEntry { SiteType site_type() const { return site_type_; } - const absl::optional& site_index() const { return site_index_; } + const std::optional& site_index() const { return site_index_; } private: // The primary site associated with this site's set. @@ -81,7 +81,7 @@ class NET_EXPORT FirstPartySetEntry { // The index of this site in the set declaration, if a meaningful index // exists. Primary sites do not have indices, nor do sites that were defined // or affected by an enterprise policy set. - absl::optional site_index_; + std::optional site_index_; }; NET_EXPORT std::ostream& operator<<( diff --git a/naiveproxy/src/net/first_party_sets/first_party_set_entry_override.h b/naiveproxy/src/net/first_party_sets/first_party_set_entry_override.h index 80c3ada308..1c9d9c9c09 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_set_entry_override.h +++ b/naiveproxy/src/net/first_party_sets/first_party_set_entry_override.h @@ -5,9 +5,10 @@ #ifndef NET_FIRST_PARTY_SETS_FIRST_PARTY_SET_ENTRY_OVERRIDE_H_ #define NET_FIRST_PARTY_SETS_FIRST_PARTY_SET_ENTRY_OVERRIDE_H_ +#include + #include "net/base/net_export.h" #include "net/first_party_sets/first_party_set_entry.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace mojo { template @@ -55,7 +56,7 @@ class NET_EXPORT FirstPartySetEntryOverride { network::mojom::FirstPartySetEntryOverrideDataView, FirstPartySetEntryOverride>; - absl::optional entry_; + std::optional entry_; }; NET_EXPORT std::ostream& operator<<(std::ostream& os, diff --git a/naiveproxy/src/net/first_party_sets/first_party_set_metadata.h b/naiveproxy/src/net/first_party_sets/first_party_set_metadata.h index b23e52575b..5c2286f487 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_set_metadata.h +++ b/naiveproxy/src/net/first_party_sets/first_party_set_metadata.h @@ -5,9 +5,10 @@ #ifndef NET_FIRST_PARTY_SETS_FIRST_PARTY_SET_METADATA_H_ #define NET_FIRST_PARTY_SETS_FIRST_PARTY_SET_METADATA_H_ +#include + #include "net/base/net_export.h" #include "net/first_party_sets/first_party_set_entry.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -31,10 +32,10 @@ class NET_EXPORT FirstPartySetMetadata { bool operator==(const FirstPartySetMetadata& other) const; bool operator!=(const FirstPartySetMetadata& other) const; - const absl::optional& frame_entry() const { + const std::optional& frame_entry() const { return frame_entry_; } - const absl::optional& top_frame_entry() const { + const std::optional& top_frame_entry() const { return top_frame_entry_; } @@ -43,8 +44,8 @@ class NET_EXPORT FirstPartySetMetadata { bool AreSitesInSameFirstPartySet() const; private: - absl::optional frame_entry_ = absl::nullopt; - absl::optional top_frame_entry_ = absl::nullopt; + std::optional frame_entry_ = std::nullopt; + std::optional top_frame_entry_ = std::nullopt; }; NET_EXPORT std::ostream& operator<<(std::ostream& os, diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.h b/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.h index 93a61e86e5..f9c67371e2 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.h +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_cache_filter.h @@ -5,10 +5,11 @@ #ifndef NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CACHE_FILTER_H_ #define NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CACHE_FILTER_H_ +#include + #include "base/containers/flat_map.h" #include "net/base/net_export.h" #include "net/base/schemeful_site.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace mojo { template @@ -33,10 +34,10 @@ class NET_EXPORT FirstPartySetsCacheFilter { // Stores the ID used to check whether cache should be bypassed. Only not // null if the request site matches the filter; nullopt if don't match. - absl::optional clear_at_run_id; + std::optional clear_at_run_id; // The ID used to mark the new cache. It should be either a positive number // or nullopt. - absl::optional browser_run_id; + std::optional browser_run_id; }; // The default cache filter is no-op. diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc index 62038e8bbb..f79c7e39fb 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.cc @@ -27,12 +27,12 @@ FirstPartySetsContextConfig FirstPartySetsContextConfig::Clone() const { bool FirstPartySetsContextConfig::operator==( const FirstPartySetsContextConfig& other) const = default; -absl::optional +std::optional FirstPartySetsContextConfig::FindOverride(const SchemefulSite& site) const { if (const auto it = customizations_.find(site); it != customizations_.end()) { return it->second; } - return absl::nullopt; + return std::nullopt; } bool FirstPartySetsContextConfig::Contains(const SchemefulSite& site) const { diff --git a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.h b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.h index 57e9d5a3a6..c49eb165a8 100644 --- a/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.h +++ b/naiveproxy/src/net/first_party_sets/first_party_sets_context_config.h @@ -5,11 +5,12 @@ #ifndef NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_ #define NET_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_ +#include + #include "base/containers/flat_map.h" #include "base/functional/function_ref.h" #include "net/base/schemeful_site.h" #include "net/first_party_sets/first_party_set_entry_override.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace mojo { template @@ -44,7 +45,7 @@ class NET_EXPORT FirstPartySetsContextConfig { // - nullopt if no override was found. // - optional(override) if an override was found. The override may be a // deletion or a modification/addition. - absl::optional FindOverride( + std::optional FindOverride( const SchemefulSite& site) const; // Returns whether an override can be found for the given site in this diff --git a/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc b/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc index c916b0f4e1..573ac50800 100644 --- a/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc +++ b/naiveproxy/src/net/first_party_sets/global_first_party_sets.cc @@ -4,6 +4,7 @@ #include "net/first_party_sets/global_first_party_sets.h" +#include #include #include @@ -20,7 +21,6 @@ #include "net/first_party_sets/first_party_set_metadata.h" #include "net/first_party_sets/first_party_sets_context_config.h" #include "net/first_party_sets/local_set_declaration.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -118,21 +118,21 @@ GlobalFirstPartySets GlobalFirstPartySets::Clone() const { manual_config_.Clone(), manual_aliases_); } -absl::optional GlobalFirstPartySets::FindEntry( +std::optional GlobalFirstPartySets::FindEntry( const SchemefulSite& site, const FirstPartySetsContextConfig& config) const { return FindEntry(site, &config); } -absl::optional GlobalFirstPartySets::FindEntry( +std::optional GlobalFirstPartySets::FindEntry( const SchemefulSite& site, const FirstPartySetsContextConfig* config) const { // Check if `site` can be found in the customizations first. if (config) { if (const auto override = config->FindOverride(site); override.has_value()) { - return override->IsDeletion() ? absl::nullopt - : absl::make_optional(override->GetEntry()); + return override->IsDeletion() ? std::nullopt + : std::make_optional(override->GetEntry()); } } @@ -140,8 +140,8 @@ absl::optional GlobalFirstPartySets::FindEntry( if (const auto manual_override = manual_config_.FindOverride(site); manual_override.has_value()) { return manual_override->IsDeletion() - ? absl::nullopt - : absl::make_optional(manual_override->GetEntry()); + ? std::nullopt + : std::make_optional(manual_override->GetEntry()); } // Finally, look up in `entries_`, applying an alias if applicable. @@ -153,7 +153,7 @@ absl::optional GlobalFirstPartySets::FindEntry( return entry_it->second; } - return absl::nullopt; + return std::nullopt; } base::flat_map @@ -162,7 +162,7 @@ GlobalFirstPartySets::FindEntries( const FirstPartySetsContextConfig& config) const { std::vector> sites_to_entries; for (const SchemefulSite& site : sites) { - const absl::optional entry = FindEntry(site, config); + const std::optional entry = FindEntry(site, config); if (entry.has_value()) { sites_to_entries.emplace_back(site, entry.value()); } @@ -174,9 +174,9 @@ FirstPartySetMetadata GlobalFirstPartySets::ComputeMetadata( const SchemefulSite& site, const SchemefulSite* top_frame_site, const FirstPartySetsContextConfig& fps_context_config) const { - absl::optional top_frame_entry = + std::optional top_frame_entry = top_frame_site ? FindEntry(*top_frame_site, fps_context_config) - : absl::nullopt; + : std::nullopt; return FirstPartySetMetadata( base::OptionalToPtr(FindEntry(site, fps_context_config)), @@ -305,7 +305,7 @@ FirstPartySetsContextConfig GlobalFirstPartySets::ComputeConfig( member == entry->second.primary() ? SiteType::kPrimary : SiteType::kAssociated, - absl::nullopt)); + std::nullopt)); } if (member == set_entry.primary()) return true; @@ -390,7 +390,7 @@ GlobalFirstPartySets::NormalizeAdditionSets( normalized .emplace(child_site_and_entry.first, FirstPartySetEntry(rep_primary, SiteType::kAssociated, - absl::nullopt)) + std::nullopt)) .second; CHECK(inserted); } diff --git a/naiveproxy/src/net/first_party_sets/global_first_party_sets.h b/naiveproxy/src/net/first_party_sets/global_first_party_sets.h index d87aaec174..0ee3c16b6e 100644 --- a/naiveproxy/src/net/first_party_sets/global_first_party_sets.h +++ b/naiveproxy/src/net/first_party_sets/global_first_party_sets.h @@ -5,6 +5,8 @@ #ifndef NET_FIRST_PARTY_SETS_GLOBAL_FIRST_PARTY_SETS_H_ #define NET_FIRST_PARTY_SETS_GLOBAL_FIRST_PARTY_SETS_H_ +#include + #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" #include "base/functional/function_ref.h" @@ -16,7 +18,6 @@ #include "net/first_party_sets/first_party_sets_context_config.h" #include "net/first_party_sets/local_set_declaration.h" #include "net/first_party_sets/sets_mutation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace mojo { template @@ -62,7 +63,7 @@ class NET_EXPORT GlobalFirstPartySets { // Respects any customization/overlay specified by `config`. This is // semi-agnostic to scheme: it just cares whether the scheme is secure or // insecure. - absl::optional FindEntry( + std::optional FindEntry( const SchemefulSite& site, const FirstPartySetsContextConfig& config) const; @@ -146,7 +147,7 @@ class NET_EXPORT GlobalFirstPartySets { // Same as the public version of FindEntry, but is allowed to omit the // `config` argument (i.e. pass nullptr instead of a reference). - absl::optional FindEntry( + std::optional FindEntry( const SchemefulSite& site, const FirstPartySetsContextConfig* config) const; diff --git a/naiveproxy/src/net/http/broken_alternative_services.cc b/naiveproxy/src/net/http/broken_alternative_services.cc index ad9045c71d..7d5c7fc1ef 100644 --- a/naiveproxy/src/net/http/broken_alternative_services.cc +++ b/naiveproxy/src/net/http/broken_alternative_services.cc @@ -284,8 +284,8 @@ void BrokenAlternativeServices::SetBrokenAndRecentlyBrokenAlternativeServices( broken_alternative_service_list_.erase(list_existing_entry_it); map_it->second = list_it; } else { - broken_alternative_service_map_.insert( - std::make_pair(broken_alternative_service, list_it)); + broken_alternative_service_map_.emplace(broken_alternative_service, + list_it); } if (recently_broken_alternative_services_.Peek( @@ -315,8 +315,8 @@ void BrokenAlternativeServices::SetBrokenAndRecentlyBrokenAlternativeServices( } void BrokenAlternativeServices::SetDelayParams( - absl::optional initial_delay, - absl::optional exponential_backoff_on_initial_delay) { + std::optional initial_delay, + std::optional exponential_backoff_on_initial_delay) { if (initial_delay.has_value()) { initial_delay_ = initial_delay.value(); } @@ -360,9 +360,8 @@ bool BrokenAlternativeServices::AddToBrokenListAndMap( // Insert |broken_alternative_service| into the list and the map. list_it = broken_alternative_service_list_.insert( - list_it, std::make_pair(broken_alternative_service, expiration)); - broken_alternative_service_map_.insert( - std::make_pair(broken_alternative_service, list_it)); + list_it, std::pair(broken_alternative_service, expiration)); + broken_alternative_service_map_.emplace(broken_alternative_service, list_it); *it = list_it; return true; diff --git a/naiveproxy/src/net/http/broken_alternative_services.h b/naiveproxy/src/net/http/broken_alternative_services.h index a706067a80..81338dc50d 100644 --- a/naiveproxy/src/net/http/broken_alternative_services.h +++ b/naiveproxy/src/net/http/broken_alternative_services.h @@ -159,9 +159,8 @@ class NET_EXPORT_PRIVATE BrokenAlternativeServices { // If values are present, sets initial_delay_ and // exponential_backoff_on_initial_delay_ which are used to calculate delay of // broken alternative services. - void SetDelayParams( - absl::optional initial_delay, - absl::optional exponential_backoff_on_initial_delay); + void SetDelayParams(std::optional initial_delay, + std::optional exponential_backoff_on_initial_delay); const BrokenAlternativeServiceList& broken_alternative_service_list() const; diff --git a/naiveproxy/src/net/http/http_auth_cache.cc b/naiveproxy/src/net/http/http_auth_cache.cc index a74721b202..70b870c0d0 100644 --- a/naiveproxy/src/net/http/http_auth_cache.cc +++ b/naiveproxy/src/net/http/http_auth_cache.cc @@ -87,7 +87,7 @@ void HttpAuthCache::SetKeyServerEntriesByNetworkAnonymizationKey( key_server_entries_by_network_anonymization_key_ = key_server_entries_by_network_anonymization_key; - std::erase_if(entries_, [](EntryMap::value_type& entry_map_pair) { + std::erase_if(entries_, [](const EntryMap::value_type& entry_map_pair) { return entry_map_pair.first.target == HttpAuth::AUTH_SERVER; }); } @@ -311,9 +311,9 @@ void HttpAuthCache::ClearEntriesAddedBetween( ClearAllEntries(); return; } - std::erase_if(entries_, [begin_time, end_time, - url_matcher](EntryMap::value_type& entry_map_pair) { - Entry& entry = entry_map_pair.second; + std::erase_if(entries_, [begin_time, end_time, url_matcher]( + const EntryMap::value_type& entry_map_pair) { + const Entry& entry = entry_map_pair.second; return entry.creation_time_ >= begin_time && entry.creation_time_ < end_time && (url_matcher ? url_matcher.Run(entry.scheme_host_port().GetURL()) diff --git a/naiveproxy/src/net/http/http_auth_controller.cc b/naiveproxy/src/net/http/http_auth_controller.cc index a3bfb7543e..dac5171d42 100644 --- a/naiveproxy/src/net/http/http_auth_controller.cc +++ b/naiveproxy/src/net/http/http_auth_controller.cc @@ -401,7 +401,7 @@ void HttpAuthController::ResetAuth(const AuthCredentials& credentials) { identity_.credentials = credentials; // auth_info_ is no longer necessary. - auth_info_ = absl::nullopt; + auth_info_ = std::nullopt; } DCHECK(identity_.source != HttpAuth::IDENT_SRC_PATH_LOOKUP); @@ -636,8 +636,7 @@ void HttpAuthController::OnGenerateAuthTokenDone(int result) { } } -void HttpAuthController::TakeAuthInfo( - absl::optional* other) { +void HttpAuthController::TakeAuthInfo(std::optional* other) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); auth_info_.swap(*other); } diff --git a/naiveproxy/src/net/http/http_auth_controller.h b/naiveproxy/src/net/http/http_auth_controller.h index 19082cb234..5c506d4c23 100644 --- a/naiveproxy/src/net/http/http_auth_controller.h +++ b/naiveproxy/src/net/http/http_auth_controller.h @@ -6,6 +6,7 @@ #define NET_HTTP_HTTP_AUTH_CONTROLLER_H_ #include +#include #include #include @@ -18,7 +19,6 @@ #include "net/http/http_auth.h" #include "net/http/http_auth_preferences.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -125,7 +125,7 @@ class NET_EXPORT_PRIVATE HttpAuthController bool NeedsHTTP11() const; // Swaps the authentication challenge info into |other|. - void TakeAuthInfo(absl::optional* other); + void TakeAuthInfo(std::optional* other); bool IsAuthSchemeDisabled(HttpAuth::Scheme scheme) const; void DisableAuthScheme(HttpAuth::Scheme scheme); @@ -221,7 +221,7 @@ class NET_EXPORT_PRIVATE HttpAuthController std::string auth_token_; // Contains information about the auth challenge. - absl::optional auth_info_; + std::optional auth_info_; // True if we've used the username:password embedded in the URL. This // makes sure we use the embedded identity only once for the transaction, diff --git a/naiveproxy/src/net/http/http_auth_handler_digest.cc b/naiveproxy/src/net/http/http_auth_handler_digest.cc index 47db0fb7eb..477b83aec2 100644 --- a/naiveproxy/src/net/http/http_auth_handler_digest.cc +++ b/naiveproxy/src/net/http/http_auth_handler_digest.cc @@ -376,8 +376,8 @@ class HttpAuthHandlerDigest::DigestContext { uint8_t md_value[EVP_MAX_MD_SIZE] = {}; unsigned int md_len = sizeof(md_value); CHECK(EVP_DigestFinal_ex(md_ctx_.get(), md_value, &md_len)); - CHECK_LE(out_len_, md_len); - return base::ToLowerASCII(base::HexEncode(md_value, out_len_)); + return base::ToLowerASCII( + base::HexEncode(base::span(md_value).first(out_len_))); } private: diff --git a/naiveproxy/src/net/http/http_auth_handler_factory.cc b/naiveproxy/src/net/http/http_auth_handler_factory.cc index b3341865a0..ca2e684a53 100644 --- a/naiveproxy/src/net/http/http_auth_handler_factory.cc +++ b/naiveproxy/src/net/http/http_auth_handler_factory.cc @@ -4,6 +4,7 @@ #include "net/http/http_auth_handler_factory.h" +#include #include #include "base/containers/contains.h" @@ -22,7 +23,6 @@ #include "net/log/net_log_values.h" #include "net/net_buildflags.h" #include "net/ssl/ssl_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/scheme_host_port.h" #if BUILDFLAG(USE_KERBEROS) @@ -36,7 +36,7 @@ base::Value::Dict NetLogParamsForCreateAuth( const std::string& challenge, const int net_error, const url::SchemeHostPort& scheme_host_port, - const absl::optional& allows_default_credentials, + const std::optional& allows_default_credentials, net::NetLogCaptureMode capture_mode) { base::Value::Dict dict; dict.Set("scheme", net::NetLogStringValue(scheme)); @@ -233,8 +233,8 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler( return NetLogParamsForCreateAuth( scheme, challenge->challenge_text(), net_error, scheme_host_port, *handler - ? absl::make_optional((*handler)->AllowsDefaultCredentials()) - : absl::nullopt, + ? std::make_optional((*handler)->AllowsDefaultCredentials()) + : std::nullopt, capture_mode); }); return net_error; @@ -255,10 +255,10 @@ bool HttpAuthHandlerRegistryFactory::IsSchemeAllowed( } #if BUILDFLAG(USE_KERBEROS) && !BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_POSIX) -absl::optional +std::optional HttpAuthHandlerRegistryFactory::GetNegotiateLibraryNameForTesting() const { if (!IsSchemeAllowed(kNegotiateAuthScheme)) - return absl::nullopt; + return std::nullopt; return reinterpret_cast( GetSchemeFactory(net::kNegotiateAuthScheme)) diff --git a/naiveproxy/src/net/http/http_auth_handler_factory.h b/naiveproxy/src/net/http/http_auth_handler_factory.h index 8c9f268a5a..a35b1cbbe1 100644 --- a/naiveproxy/src/net/http/http_auth_handler_factory.h +++ b/naiveproxy/src/net/http/http_auth_handler_factory.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,6 @@ #include "net/http/http_auth_scheme.h" #include "net/http/url_security_manager.h" #include "net/net_buildflags.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace url { class SchemeHostPort; @@ -238,7 +238,7 @@ class NET_EXPORT HttpAuthHandlerRegistryFactory std::unique_ptr* handler) override; #if BUILDFLAG(USE_KERBEROS) && !BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_POSIX) - absl::optional GetNegotiateLibraryNameForTesting() const; + std::optional GetNegotiateLibraryNameForTesting() const; #endif // Returns true if the scheme is allowed to be used for all origins. An auth diff --git a/naiveproxy/src/net/http/http_auth_handler_negotiate.cc b/naiveproxy/src/net/http/http_auth_handler_negotiate.cc index 57f64d52cb..4e7f82268d 100644 --- a/naiveproxy/src/net/http/http_auth_handler_negotiate.cc +++ b/naiveproxy/src/net/http/http_auth_handler_negotiate.cc @@ -44,8 +44,7 @@ base::Value::Dict NetLogParameterChannelBindings( if (!NetLogCaptureIncludesSocketBytes(capture_mode)) return dict; - dict.Set("token", base::HexEncode(channel_binding_token.data(), - channel_binding_token.size())); + dict.Set("token", base::HexEncode(channel_binding_token)); return dict; } diff --git a/naiveproxy/src/net/http/http_auth_preferences.h b/naiveproxy/src/net/http/http_auth_preferences.h index f14d55e6fb..127e47cd2a 100644 --- a/naiveproxy/src/net/http/http_auth_preferences.h +++ b/naiveproxy/src/net/http/http_auth_preferences.h @@ -6,6 +6,7 @@ #define NET_HTTP_HTTP_AUTH_PREFERENCES_H_ #include +#include #include #include @@ -14,7 +15,6 @@ #include "build/chromeos_buildflags.h" #include "net/base/net_export.h" #include "net/http/http_auth.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace url { class SchemeHostPort; @@ -92,12 +92,12 @@ class NET_EXPORT HttpAuthPreferences { } #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) - const absl::optional>& allowed_schemes() const { + const std::optional>& allowed_schemes() const { return allowed_schemes_; } void set_allowed_schemes( - const absl::optional>& allowed_schemes) { + const std::optional>& allowed_schemes) { allowed_schemes_ = allowed_schemes; } @@ -141,7 +141,7 @@ class NET_EXPORT HttpAuthPreferences { bool allow_gssapi_library_load_ = true; #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) - absl::optional> allowed_schemes_; + std::optional> allowed_schemes_; std::unique_ptr security_manager_; base::RepeatingCallback http_auth_scheme_filter_ = diff --git a/naiveproxy/src/net/http/http_cache.cc b/naiveproxy/src/net/http/http_cache.cc index 6cf848241d..997cdff1bf 100644 --- a/naiveproxy/src/net/http/http_cache.cc +++ b/naiveproxy/src/net/http/http_cache.cc @@ -4,6 +4,7 @@ #include "net/http/http_cache.h" +#include #include #include "base/compiler_specific.h" @@ -49,7 +50,6 @@ #include "net/http/http_util.h" #include "net/log/net_log_with_source.h" #include "net/quic/quic_server_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #if BUILDFLAG(IS_POSIX) #include @@ -604,7 +604,7 @@ std::string HttpCache::GetResourceURLFromHttpCacheKey(const std::string& key) { // static // Generate a key that can be used inside the cache. -absl::optional HttpCache::GenerateCacheKey( +std::optional HttpCache::GenerateCacheKey( const GURL& url, int load_flags, const NetworkIsolationKey& network_isolation_key, @@ -626,7 +626,7 @@ absl::optional HttpCache::GenerateCacheKey( // confused with a single-keyed entry). Separate the origin and url // with invalid whitespace character |kDoubleKeySeparator|. if (network_isolation_key.IsTransient()) { - return absl::nullopt; + return std::nullopt; } std::string subframe_document_resource_prefix = is_subframe_document_resource ? kSubframeDocumentResourcePrefix : ""; @@ -647,7 +647,7 @@ absl::optional HttpCache::GenerateCacheKey( } // static -absl::optional HttpCache::GenerateCacheKeyForRequest( +std::optional HttpCache::GenerateCacheKeyForRequest( const HttpRequestInfo* request) { CHECK(request); const int64_t upload_data_identifier = diff --git a/naiveproxy/src/net/http/http_cache.h b/naiveproxy/src/net/http/http_cache.h index 6bafcc997f..96404d0493 100644 --- a/naiveproxy/src/net/http/http_cache.h +++ b/naiveproxy/src/net/http/http_cache.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include "net/base/request_priority.h" #include "net/disk_cache/disk_cache.h" #include "net/http/http_transaction_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -259,13 +259,13 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory { // configured to be split by the NetworkIsolationKey, and the // NetworkIsolationKey is transient, in which case nothing should generally be // stored to disk. - static absl::optional GenerateCacheKey( + static std::optional GenerateCacheKey( const GURL& url, int load_flags, const NetworkIsolationKey& network_isolation_key, int64_t upload_data_identifier, bool is_subframe_document_resource); - static absl::optional GenerateCacheKeyForRequest( + static std::optional GenerateCacheKeyForRequest( const HttpRequestInfo* request); // Enable split cache feature if not already overridden in the feature list. diff --git a/naiveproxy/src/net/http/http_cache_transaction.cc b/naiveproxy/src/net/http/http_cache_transaction.cc index ead08e8581..800fb77e6f 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.cc +++ b/naiveproxy/src/net/http/http_cache_transaction.cc @@ -97,8 +97,8 @@ enum ExternallyConditionalizedType { }; bool ShouldByPassCacheForFirstPartySets( - const absl::optional& clear_at_run_id, - const absl::optional& written_at_run_id) { + const std::optional& clear_at_run_id, + const std::optional& written_at_run_id) { return clear_at_run_id.has_value() && (!written_at_run_id.has_value() || written_at_run_id.value() < clear_at_run_id.value()); @@ -3981,7 +3981,7 @@ void HttpCache::Transaction::OnCacheIOComplete(int result) { // transaction was being processed that now needs to be processed. if (pending_io_result_) { int stored_result = pending_io_result_.value(); - pending_io_result_ = absl::nullopt; + pending_io_result_ = std::nullopt; OnIOComplete(stored_result); } } else { diff --git a/naiveproxy/src/net/http/http_cache_transaction.h b/naiveproxy/src/net/http/http_cache_transaction.h index 764ef7c9cb..21bf29f096 100644 --- a/naiveproxy/src/net/http/http_cache_transaction.h +++ b/naiveproxy/src/net/http/http_cache_transaction.h @@ -609,7 +609,7 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { // If a pending async HTTPCache transaction takes longer than the parallel // Network IO, this will store the result of the Network IO operation until // the cache transaction completes (or times out). - absl::optional pending_io_result_ = absl::nullopt; + std::optional pending_io_result_ = std::nullopt; // Used for tracing. const uint64_t trace_id_; @@ -647,7 +647,7 @@ class NET_EXPORT_PRIVATE HttpCache::Transaction : public HttpTransaction { // and modifies the members for future transactions. Then, // WriteResponseInfoToEntry() writes |updated_prefetch_response_| to the cache // entry if it is populated, or |response_| otherwise. Finally, - // WriteResponseInfoToEntry() resets this to absl::nullopt. + // WriteResponseInfoToEntry() resets this to std::nullopt. std::unique_ptr updated_prefetch_response_; raw_ptr new_response_ = diff --git a/naiveproxy/src/net/http/http_cache_writers.cc b/naiveproxy/src/net/http/http_cache_writers.cc index 2cbb40baf7..6f6190896b 100644 --- a/naiveproxy/src/net/http/http_cache_writers.cc +++ b/naiveproxy/src/net/http/http_cache_writers.cc @@ -74,7 +74,7 @@ int HttpCache::Writers::Read(scoped_refptr buf, // with the data returned from that read. if (next_state_ != State::NONE) { WaitingForRead read_info(buf, buf_len, std::move(callback)); - waiting_for_read_.insert(std::make_pair(transaction, std::move(read_info))); + waiting_for_read_.emplace(transaction, std::move(read_info)); return ERR_IO_PENDING; } diff --git a/naiveproxy/src/net/http/http_content_disposition.cc b/naiveproxy/src/net/http/http_content_disposition.cc index f70d98eb3c..6e8e2dc04e 100644 --- a/naiveproxy/src/net/http/http_content_disposition.cc +++ b/naiveproxy/src/net/http/http_content_disposition.cc @@ -29,7 +29,7 @@ enum RFC2047EncodingType { bool DecodeQEncoding(base::StringPiece input, std::string* output) { std::string temp; temp.reserve(input.size()); - for (auto* it = input.begin(); it != input.end(); ++it) { + for (auto it = input.begin(); it != input.end(); ++it) { if (*it == '_') { temp.push_back(' '); } else if (*it == '=') { diff --git a/naiveproxy/src/net/http/http_network_session.h b/naiveproxy/src/net/http/http_network_session.h index 36dc957aff..60e1e564da 100644 --- a/naiveproxy/src/net/http/http_network_session.h +++ b/naiveproxy/src/net/http/http_network_session.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -37,7 +38,6 @@ #include "net/spdy/spdy_session_pool.h" #include "net/ssl/ssl_client_session_cache.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class Value; @@ -127,7 +127,7 @@ struct NET_EXPORT HttpNetworkSessionParams { // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00. // The same frame will be sent out on all connections to prevent the retry // logic from hiding broken servers. - absl::optional greased_http2_frame; + std::optional greased_http2_frame; // If set, the HEADERS frame carrying a request without body will not have // the END_STREAM flag set. The stream will be closed by a subsequent empty // DATA frame with END_STREAM. Does not affect bidirectional or proxy diff --git a/naiveproxy/src/net/http/http_network_transaction.cc b/naiveproxy/src/net/http/http_network_transaction.cc index fd8feb000f..afd3d5abf4 100644 --- a/naiveproxy/src/net/http/http_network_transaction.cc +++ b/naiveproxy/src/net/http/http_network_transaction.cc @@ -443,7 +443,8 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, // also don't worry about this for an HTTPS Proxy, because the // communication with the proxy is secure. // See http://crbug.com/8473. - DCHECK(proxy_info_.is_http_like()); + DCHECK(proxy_info_.AnyProxyInChain( + [](const ProxyServer& s) { return s.is_http_like(); })); DCHECK_EQ(headers->response_code(), HTTP_PROXY_AUTHENTICATION_REQUIRED); return ERR_TUNNEL_CONNECTION_FAILED; } @@ -1664,12 +1665,17 @@ int HttpNetworkTransaction::HandleSSLClientAuthError(int error) { host_port_pair = HostPortPair::FromURL(request_->url); } else { CHECK(proxy_info_.proxy_chain().is_single_proxy()); - host_port_pair = proxy_info_.proxy_chain() - .GetProxyServer(/*chain_index=*/0) - .host_port_pair(); + host_port_pair = proxy_info_.proxy_chain().First().host_port_pair(); + } + + // Check that something in the proxy chain or endpoint are using HTTPS. + if (DCHECK_IS_ON()) { + bool server_using_tls = IsSecureRequest(); + bool proxy_using_tls = proxy_info_.AnyProxyInChain( + [](const ProxyServer& s) { return s.is_secure_http_like(); }); + DCHECK(server_using_tls || proxy_using_tls); } - DCHECK((is_server && IsSecureRequest()) || proxy_info_.is_secure_http_like()); if (session_->ssl_client_context()->ClearClientCertificate(host_port_pair)) { // The private key handle may have gone stale due to, e.g., the user // unplugging their smartcard. Operating systems do not provide reliable @@ -1695,7 +1701,7 @@ int HttpNetworkTransaction::HandleSSLClientAuthError(int error) { } // static -absl::optional +std::optional HttpNetworkTransaction::GetRetryReasonForIOError(int error) { switch (error) { case ERR_CONNECTION_RESET: @@ -1723,7 +1729,7 @@ HttpNetworkTransaction::GetRetryReasonForIOError(int error) { case ERR_QUIC_PROTOCOL_ERROR: return RetryReason::kQuicProtocolError; } - return absl::nullopt; + return std::nullopt; } // This method determines whether it is safe to resend the request after an @@ -1740,7 +1746,7 @@ int HttpNetworkTransaction::HandleIOError(int error) { GenerateNetworkErrorLoggingReportIfError(error); #endif // BUILDFLAG(ENABLE_REPORTING) - absl::optional retry_reason = + std::optional retry_reason = GetRetryReasonForIOError(error); if (!retry_reason) { return error; @@ -1998,19 +2004,17 @@ GURL HttpNetworkTransaction::AuthURL(HttpAuth::Target target) const { switch (target) { case HttpAuth::AUTH_PROXY: { // TODO(https://crbug.com/1491092): Update to handle multi-proxy chain. + CHECK(proxy_info_.proxy_chain().is_single_proxy()); if (!proxy_info_.proxy_chain().IsValid() || - proxy_info_.proxy_chain().is_direct() || - !proxy_info_.proxy_chain().is_single_proxy()) { + proxy_info_.proxy_chain().is_direct()) { return GURL(); // There is no proxy chain. } // TODO(https://crbug.com/1103768): Mapping proxy addresses to // URLs is a lossy conversion, shouldn't do this. + auto& proxy_server = proxy_info_.proxy_chain().First(); const char* scheme = - proxy_info_.is_secure_http_like() ? "https://" : "http://"; - return GURL(scheme + proxy_info_.proxy_chain() - .GetProxyServer(/*chain_index=*/0) - .host_port_pair() - .ToString()); + proxy_server.is_secure_http_like() ? "https://" : "http://"; + return GURL(scheme + proxy_server.host_port_pair().ToString()); } case HttpAuth::AUTH_SERVER: if (ForWebSocketHandshake()) { @@ -2092,9 +2096,9 @@ void HttpNetworkTransaction::RecordQuicProtocolErrorMetrics( if (!stream_) { return; } - absl::optional connection_error = + std::optional connection_error = stream_->GetQuicErrorCode(); - absl::optional stream_error = + std::optional stream_error = stream_->GetQuicRstStreamErrorCode(); if (!connection_error || !stream_error) { return; @@ -2125,7 +2129,6 @@ void HttpNetworkTransaction::SetProxyInfoInResponse( const ProxyInfo& proxy_info, HttpResponseInfo* response_info) { response_info->was_fetched_via_proxy = !proxy_info.is_direct(); - response_info->was_ip_protected = proxy_info.is_for_ip_protection(); response_info->was_mdl_match = proxy_info.is_mdl_match(); if (response_info->was_fetched_via_proxy && !proxy_info.is_empty()) { response_info->proxy_chain = proxy_info.proxy_chain(); diff --git a/naiveproxy/src/net/http/http_network_transaction.h b/naiveproxy/src/net/http/http_network_transaction.h index 6558e7d40e..4eb4f74355 100644 --- a/naiveproxy/src/net/http/http_network_transaction.h +++ b/naiveproxy/src/net/http/http_network_transaction.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -35,7 +36,6 @@ #include "net/socket/connection_attempts.h" #include "net/ssl/ssl_config.h" #include "net/websockets/websocket_handshake_stream_base.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -291,7 +291,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction kQuicProtocolError = 18, kMaxValue = kQuicProtocolError, }; - static absl::optional GetRetryReasonForIOError(int error); + static std::optional GetRetryReasonForIOError(int error); // Resets the connection and the request headers for resend. Called when // ShouldResendRequest() is true. @@ -505,7 +505,7 @@ class NET_EXPORT_PRIVATE HttpNetworkTransaction // Set to true when the server required HTTP/1.1 fallback. bool http_1_1_was_required_ = false; - absl::optional quic_protocol_error_retry_delay_; + std::optional quic_protocol_error_retry_delay_; }; } // namespace net diff --git a/naiveproxy/src/net/http/http_no_vary_search_data.cc b/naiveproxy/src/net/http/http_no_vary_search_data.cc index 294ad4f0c6..56c0f10749 100644 --- a/naiveproxy/src/net/http/http_no_vary_search_data.cc +++ b/naiveproxy/src/net/http/http_no_vary_search_data.cc @@ -17,14 +17,14 @@ namespace net { namespace { // Tries to parse a list of ParameterizedItem as a list of strings. -// Returns absl::nullopt if unsuccessful. -absl::optional> ParseStringList( +// Returns std::nullopt if unsuccessful. +std::optional> ParseStringList( const std::vector& items) { std::vector keys; keys.reserve(items.size()); for (const auto& item : items) { if (!item.item.is_string()) { - return absl::nullopt; + return std::nullopt; } keys.push_back(UnescapePercentEncodedUrl(item.item.GetString())); } diff --git a/naiveproxy/src/net/http/http_proxy_connect_job.cc b/naiveproxy/src/net/http/http_proxy_connect_job.cc index 1a031ed82b..dfbadbc013 100644 --- a/naiveproxy/src/net/http/http_proxy_connect_job.cc +++ b/naiveproxy/src/net/http/http_proxy_connect_job.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include "base/functional/bind.h" @@ -24,12 +25,14 @@ #include "net/base/http_user_agent_settings.h" #include "net/base/net_errors.h" #include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" #include "net/nqe/network_quality_estimator.h" #include "net/quic/quic_http_utils.h" #include "net/quic/quic_proxy_client_socket.h" +#include "net/quic/quic_session_key.h" #include "net/quic/quic_session_pool.h" #include "net/socket/client_socket_handle.h" #include "net/socket/next_proto.h" @@ -42,7 +45,6 @@ #include "net/spdy/spdy_session_pool.h" #include "net/spdy/spdy_stream.h" #include "net/ssl/ssl_cert_request_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -306,7 +308,7 @@ base::TimeDelta HttpProxyConnectJob::AlternateNestedConnectionTimeout( return default_alternate_timeout; } - absl::optional http_rtt_estimate = + std::optional http_rtt_estimate = network_quality_estimator->GetHttpRTT(); if (!http_rtt_estimate) { return default_alternate_timeout; @@ -598,7 +600,7 @@ int HttpProxyConnectJob::DoHttpProxyConnectComplete(int result) { } if (result == OK) { - SetSocket(std::move(transport_socket_), /*dns_aliases=*/absl::nullopt); + SetSocket(std::move(transport_socket_), /*dns_aliases=*/std::nullopt); } return result; @@ -689,15 +691,21 @@ int HttpProxyConnectJob::DoQuicProxyCreateSession() { // Use default QUIC version, which is the version listed supported version. quic::ParsedQuicVersion quic_version = common_connect_job_params()->quic_supported_versions->front(); + // TODO(https://crbug.com/1491092): Update to handle multi-proxy chains. We + // will need to create a proxy chain corresponding to all proxy servers up to + // but not including the one we are connecting to (or ProxyChain::Direct for + // the first proxy server) and use that instead of ProxyChain::Direct() below. + CHECK(!params_->proxy_chain().is_multi_proxy()); return quic_session_request_->Request( // TODO(crbug.com/1206799) Pass the destination directly once it's // converted to contain scheme. url::SchemeHostPort(url::kHttpsScheme, proxy_server.host(), proxy_server.port()), - quic_version, ssl_params->privacy_mode(), kH2QuicTunnelPriority, + quic_version, ProxyChain::Direct(), params_->traffic_annotation(), + SessionUsage::kProxy, ssl_params->privacy_mode(), kH2QuicTunnelPriority, socket_tag(), params_->network_anonymization_key(), params_->secure_dns_policy(), - /*use_dns_aliases=*/false, /*require_dns_https_alpn=*/false, + /*require_dns_https_alpn=*/false, ssl_params->ssl_config().GetCertVerifyFlags(), GURL("https://" + proxy_server.ToString()), net_log(), &quic_net_error_details_, @@ -856,11 +864,15 @@ SpdySessionKey HttpProxyConnectJob::CreateSpdySessionKey() const { if (params_->proxy_chain_index() == 0) { DCHECK(session_key_proxy_chain.is_direct()); } - return SpdySessionKey(params_->proxy_server().host_port_pair(), - session_key_proxy_chain, PRIVACY_MODE_DISABLED, - SpdySessionKey::IsProxySession::kTrue, socket_tag(), - params_->network_anonymization_key(), - params_->secure_dns_policy()); + + // Note that `disable_cert_network_fetches` must be true for proxies to avoid + // deadlock. See comment on + // `SSLConfig::disable_cert_verification_network_fetches`. + return SpdySessionKey( + params_->proxy_server().host_port_pair(), PRIVACY_MODE_DISABLED, + session_key_proxy_chain, SessionUsage::kProxy, socket_tag(), + params_->network_anonymization_key(), params_->secure_dns_policy(), + /*disable_cert_verification_network_fetches=*/true); } } // namespace net diff --git a/naiveproxy/src/net/http/http_request_headers.cc b/naiveproxy/src/net/http/http_request_headers.cc index 981c1e3d63..86a7f92d38 100644 --- a/naiveproxy/src/net/http/http_request_headers.cc +++ b/naiveproxy/src/net/http/http_request_headers.cc @@ -26,7 +26,7 @@ namespace net { namespace { bool SupportsStreamType( - const absl::optional>& + const std::optional>& accepted_stream_types, SourceStream::SourceType type) { if (!accepted_stream_types) @@ -243,7 +243,7 @@ base::Value::Dict HttpRequestHeaders::NetLogParams( void HttpRequestHeaders::SetAcceptEncodingIfMissing( const GURL& url, - const absl::optional>& + const std::optional>& accepted_stream_types, bool enable_brotli, bool enable_zstd) { diff --git a/naiveproxy/src/net/http/http_request_headers.h b/naiveproxy/src/net/http/http_request_headers.h index fe6e7543b3..9cfe1466c0 100644 --- a/naiveproxy/src/net/http/http_request_headers.h +++ b/naiveproxy/src/net/http/http_request_headers.h @@ -11,6 +11,7 @@ #define NET_HTTP_HTTP_REQUEST_HEADERS_H_ #include +#include #include #include @@ -20,7 +21,6 @@ #include "net/base/net_export.h" #include "net/filter/source_stream.h" #include "net/log/net_log_capture_mode.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -196,7 +196,7 @@ class NET_EXPORT HttpRequestHeaders { // it does not exist. "br" is appended only when `enable_brotli` is true. void SetAcceptEncodingIfMissing( const GURL& url, - const absl::optional>& + const std::optional>& accepted_stream_types, bool enable_brotli, bool enable_zstd); diff --git a/naiveproxy/src/net/http/http_request_info.h b/naiveproxy/src/net/http/http_request_info.h index e318ba4078..3d445e45f3 100644 --- a/naiveproxy/src/net/http/http_request_info.h +++ b/naiveproxy/src/net/http/http_request_info.h @@ -5,6 +5,7 @@ #ifndef NET_HTTP_HTTP_REQUEST_INFO_H__ #define NET_HTTP_HTTP_REQUEST_INFO_H__ +#include #include #include "base/memory/raw_ptr.h" @@ -18,7 +19,6 @@ #include "net/http/http_request_headers.h" #include "net/socket/socket_tag.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -97,11 +97,11 @@ struct NET_EXPORT HttpRequestInfo { // TODO(https://crbug.com/1136054): Investigate migrating the one consumer of // this to NetworkIsolationKey::TopFrameSite(). That gives more consistent /// behavior, and may still provide useful metrics. - absl::optional possibly_top_frame_origin; + std::optional possibly_top_frame_origin; // The frame origin associated with a request. This is used to isolate shared // dictionaries between different frame origins. - absl::optional frame_origin; + std::optional frame_origin; // Idempotency of the request, which determines that if it is safe to enable // 0-RTT for the request. By default, 0-RTT is only enabled for safe @@ -115,11 +115,11 @@ struct NET_EXPORT HttpRequestInfo { // If not null, the value is used to evaluate whether the cache entry should // be bypassed; if is null, that means the request site does not match the // filter. - absl::optional fps_cache_filter; + std::optional fps_cache_filter; // Use as ID to mark the cache entry when persisting. Should be a positive // number once set. - absl::optional browser_run_id; + std::optional browser_run_id; }; } // namespace net diff --git a/naiveproxy/src/net/http/http_response_headers.cc b/naiveproxy/src/net/http/http_response_headers.cc index 44b61d3b57..813fa3c89e 100644 --- a/naiveproxy/src/net/http/http_response_headers.cc +++ b/naiveproxy/src/net/http/http_response_headers.cc @@ -147,9 +147,8 @@ int ParseStatus(base::StringPiece status, std::string& append_to) { // Skip whitespace. Tabs are not skipped, for backwards compatibility. RemoveLeadingSpaces(&status); - const char* first_non_digit = - std::find_if(status.begin(), status.end(), - [](char c) { return !base::IsAsciiDigit(c); }); + auto first_non_digit = std::ranges::find_if( + status, [](char c) { return !base::IsAsciiDigit(c); }); if (first_non_digit == status.begin()) { DVLOG(1) << "missing response status number; assuming 200"; @@ -1566,7 +1565,7 @@ bool HttpResponseHeaders::StrictlyEquals( offsets_match(lhs.value_begin, rhs.value_begin) && offsets_match(lhs.value_end, rhs.value_end); - }) == std::make_pair(parsed_.end(), other.parsed_.end()); + }) == std::pair(parsed_.end(), other.parsed_.end()); } } // namespace net diff --git a/naiveproxy/src/net/http/http_response_info.cc b/naiveproxy/src/net/http/http_response_info.cc index adaa2e46b7..fdbf5f0ca4 100644 --- a/naiveproxy/src/net/http/http_response_info.cc +++ b/naiveproxy/src/net/http/http_response_info.cc @@ -4,6 +4,8 @@ #include "net/http/http_response_info.h" +#include + #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/pickle.h" @@ -16,7 +18,6 @@ #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_connection_status_flags.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/ssl.h" using base::Time; @@ -348,7 +349,7 @@ bool HttpResponseInfo::InitFromPickle(const base::Pickle& pickle, int64_t id; if (!iter.ReadInt64(&id)) return false; - browser_run_id = absl::make_optional(id); + browser_run_id = std::make_optional(id); } did_use_shared_dictionary = diff --git a/naiveproxy/src/net/http/http_response_info.h b/naiveproxy/src/net/http/http_response_info.h index 2154ef1630..d4c56c2c96 100644 --- a/naiveproxy/src/net/http/http_response_info.h +++ b/naiveproxy/src/net/http/http_response_info.h @@ -5,6 +5,7 @@ #ifndef NET_HTTP_HTTP_RESPONSE_INFO_H_ #define NET_HTTP_HTTP_RESPONSE_INFO_H_ +#include #include #include @@ -18,7 +19,6 @@ #include "net/http/http_connection_info.h" #include "net/http/http_vary_data.h" #include "net/ssl/ssl_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class Pickle; @@ -120,12 +120,6 @@ class NET_EXPORT HttpResponseInfo { // `InitFromPickle()` then use it to replace `was_fetched_via_proxy`. ProxyChain proxy_chain; - // Whether this request was covered by IP protection. This may be true even if - // the IP Protection proxy chain is `direct://`. It is false if `was_cached`. - // This field is not persisted by `Persist()` and not restored by - // `InitFromPickle()`. - bool was_ip_protected = false; - // Whether this request was eligible for IP Protection based on the request // being a match to the masked domain list, if available. // This field is not persisted by `Persist()` and not restored by @@ -187,7 +181,7 @@ class NET_EXPORT HttpResponseInfo { // If the response headers indicate a 401 or 407 failure, then this structure // will contain additional information about the authentication challenge. - absl::optional auth_challenge; + std::optional auth_challenge; // The SSL client certificate request info. // TODO(wtc): does this really belong in HttpResponseInfo? I put it here @@ -215,7 +209,7 @@ class NET_EXPORT HttpResponseInfo { // If not null, this indicates the response is stored during a certain browser // session. Used for filtering cache access. - absl::optional browser_run_id; + std::optional browser_run_id; // True if the response used a shared dictionary for decoding its body. bool did_use_shared_dictionary = false; diff --git a/naiveproxy/src/net/http/http_server_properties.cc b/naiveproxy/src/net/http/http_server_properties.cc index 455d55ff5b..827ea33017 100644 --- a/naiveproxy/src/net/http/http_server_properties.cc +++ b/naiveproxy/src/net/http/http_server_properties.cc @@ -573,8 +573,8 @@ void HttpServerProperties::SetMaxServerConfigsStoredInProperties( } void HttpServerProperties::SetBrokenAlternativeServicesDelayParams( - absl::optional initial_delay, - absl::optional exponential_backoff_on_initial_delay) { + std::optional initial_delay, + std::optional exponential_backoff_on_initial_delay) { broken_alternative_services_.SetDelayParams( initial_delay, exponential_backoff_on_initial_delay); } diff --git a/naiveproxy/src/net/http/http_server_properties.h b/naiveproxy/src/net/http/http_server_properties.h index 71b7fe9656..0f5832482e 100644 --- a/naiveproxy/src/net/http/http_server_properties.h +++ b/naiveproxy/src/net/http/http_server_properties.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" // TODO(willchan): Reconsider this. #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/scheme_host_port.h" namespace base { @@ -150,14 +150,14 @@ class NET_EXPORT HttpServerProperties // indicates unknown. The difference between false and not set only matters // when loading from disk, when an initialized false value will take // priority over a not set value. - absl::optional supports_spdy; + std::optional supports_spdy; // True if the server has previously indicated it required HTTP/1.1. Unlike // other fields, not persisted to disk. - absl::optional requires_http11; + std::optional requires_http11; - absl::optional alternative_services; - absl::optional server_network_stats; + std::optional alternative_services; + std::optional server_network_stats; }; struct NET_EXPORT ServerInfoMapKey { @@ -427,8 +427,8 @@ class NET_EXPORT HttpServerProperties // exponential_backoff_on_initial_delay which are used to calculate delay of // broken alternative services. void SetBrokenAlternativeServicesDelayParams( - absl::optional initial_delay, - absl::optional exponential_backoff_on_initial_delay); + std::optional initial_delay, + std::optional exponential_backoff_on_initial_delay); // Returns whether HttpServerProperties is initialized. bool IsInitialized() const; diff --git a/naiveproxy/src/net/http/http_server_properties_manager.cc b/naiveproxy/src/net/http/http_server_properties_manager.cc index db9a89000b..9833d9c626 100644 --- a/naiveproxy/src/net/http/http_server_properties_manager.cc +++ b/naiveproxy/src/net/http/http_server_properties_manager.cc @@ -5,6 +5,7 @@ #include "net/http/http_server_properties_manager.h" #include +#include #include #include "base/containers/adapters.h" @@ -23,7 +24,6 @@ #include "net/base/privacy_mode.h" #include "net/http/http_server_properties.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_hostname_utils.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -69,7 +69,7 @@ const char kBrokenCountKey[] = "broken_count"; // services. Also checks if an alternative service for the same canonical suffix // has already been saved, and if so, returns an empty list. AlternativeServiceInfoVector GetAlternativeServiceToPersist( - const absl::optional& alternative_services, + const std::optional& alternative_services, const HttpServerProperties::ServerInfoMapKey& server_info_key, base::Time now, const HttpServerPropertiesManager::GetCannonicalSuffix& @@ -233,7 +233,7 @@ void HttpServerPropertiesManager::ReadPrefs( net_log_.AddEvent(NetLogEventType::HTTP_SERVER_PROPERTIES_UPDATE_CACHE, [&] { return http_server_properties_dict.Clone(); }); - absl::optional maybe_version_number = + std::optional maybe_version_number = http_server_properties_dict.FindInt(kVersionKey); if (!maybe_version_number.has_value() || *maybe_version_number != kVersionNumber) { @@ -354,7 +354,7 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices( // Read broken-count and add an entry for |alt_service| into // |recently_broken_alternative_services|. if (broken_alt_svc_entry_dict.Find(kBrokenCountKey)) { - absl::optional broken_count = + std::optional broken_count = broken_alt_svc_entry_dict.FindInt(kBrokenCountKey); if (!broken_count.has_value()) { DVLOG(1) << "Recently broken alternative service has malformed " @@ -390,10 +390,10 @@ void HttpServerPropertiesManager::AddToBrokenAlternativeServices( base::TimeTicks expiration_time_ticks = clock_->NowTicks() + (base::Time::FromTimeT(expiration_time_t) - base::Time::Now()); - broken_alternative_service_list->push_back(std::make_pair( + broken_alternative_service_list->emplace_back( BrokenAlternativeService(alt_service, network_anonymization_key, use_network_anonymization_key), - expiration_time_ticks)); + expiration_time_ticks); contains_broken_count_or_broken_until = true; } @@ -478,7 +478,7 @@ bool HttpServerPropertiesManager::ParseAlternativeServiceDict( alternative_service->host = host; // Port is mandatory. - absl::optional maybe_port = dict.FindInt(kPortKey); + std::optional maybe_port = dict.FindInt(kPortKey); if (!maybe_port.has_value() || !IsPortValid(maybe_port.value())) { DVLOG(1) << "Malformed alternative service port under: " << parsing_under; return false; @@ -618,7 +618,7 @@ void HttpServerPropertiesManager::ParseNetworkStats( if (!server_network_stats_dict) { return; } - absl::optional maybe_srtt = server_network_stats_dict->FindInt(kSrttKey); + std::optional maybe_srtt = server_network_stats_dict->FindInt(kSrttKey); if (!maybe_srtt.has_value()) { DVLOG(1) << "Malformed ServerNetworkStats for server: " << server.Serialize(); diff --git a/naiveproxy/src/net/http/http_stream.cc b/naiveproxy/src/net/http/http_stream.cc index d1e6acec56..9089df033e 100644 --- a/naiveproxy/src/net/http/http_stream.cc +++ b/naiveproxy/src/net/http/http_stream.cc @@ -6,13 +6,13 @@ namespace net { -absl::optional HttpStream::GetQuicErrorCode() const { - return absl::nullopt; +std::optional HttpStream::GetQuicErrorCode() const { + return std::nullopt; } -absl::optional +std::optional HttpStream::GetQuicRstStreamErrorCode() const { - return absl::nullopt; + return std::nullopt; } } // namespace net diff --git a/naiveproxy/src/net/http/http_stream.h b/naiveproxy/src/net/http/http_stream.h index 7e373920e0..3b0a1d01b6 100644 --- a/naiveproxy/src/net/http/http_stream.h +++ b/naiveproxy/src/net/http/http_stream.h @@ -14,6 +14,7 @@ #include #include +#include #include #include "base/strings/string_piece.h" @@ -25,7 +26,6 @@ #include "net/base/request_priority.h" #include "net/http/http_raw_request_headers.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_error_codes.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -216,11 +216,11 @@ class NET_EXPORT_PRIVATE HttpStream { // If `this` is using a Quic stream, set the `connection_error` of the Quic // stream. Otherwise returns nullopt. - virtual absl::optional GetQuicErrorCode() const; + virtual std::optional GetQuicErrorCode() const; // If `this` is using a Quic stream, set the `stream_error' status of the Quic // stream. Otherwise returns nullopt. - virtual absl::optional + virtual std::optional GetQuicRstStreamErrorCode() const; }; diff --git a/naiveproxy/src/net/http/http_stream_factory_job.cc b/naiveproxy/src/net/http/http_stream_factory_job.cc index dadd26ab5e..49ca92d472 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job.cc @@ -20,7 +20,9 @@ #include "net/base/host_port_pair.h" #include "net/base/load_flags.h" #include "net/base/port_util.h" +#include "net/base/proxy_chain.h" #include "net/base/proxy_delegate.h" +#include "net/base/session_usage.h" #include "net/cert/cert_verifier.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/bidirectional_stream_impl.h" @@ -37,6 +39,7 @@ #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/quic/bidirectional_stream_quic_impl.h" #include "net/quic/quic_http_stream.h" +#include "net/quic/quic_session_key.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/connect_job.h" @@ -47,6 +50,7 @@ #include "net/spdy/spdy_http_stream.h" #include "net/spdy/spdy_session.h" #include "net/ssl/ssl_cert_request_info.h" +#include "url/gurl.h" #include "url/scheme_host_port.h" #include "url/url_constants.h" @@ -139,11 +143,9 @@ HttpStreamFactory::Job::Job( is_websocket_ && origin_url_.SchemeIs(url::kWssScheme) && // TODO(https://crbug.com/1277306): Remove the proxy check. proxy_info_.is_direct()), - // Don't use IP connection pooling for HTTP over HTTPS proxies. It doesn't - // get us much, and testing it is more effort than its worth. + // Only support IP-based pooling for non-proxied streams. enable_ip_based_pooling_(enable_ip_based_pooling && - !(proxy_info_.is_secure_http_like() && - origin_url_.SchemeIs(url::kHttpScheme))), + proxy_info.is_direct()), delegate_(delegate), job_type_(job_type), using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) || @@ -159,15 +161,11 @@ HttpStreamFactory::Job::Job( quic_version_(quic_version), expect_spdy_(alternative_protocol == kProtoHTTP2 && !using_quic_), quic_request_(session_->quic_session_pool()), - spdy_session_key_( - using_quic_ - ? SpdySessionKey() - : GetSpdySessionKey(proxy_info_.proxy_chain(), - origin_url_, - request_info_.privacy_mode, - request_info_.socket_tag, - request_info_.network_anonymization_key, - request_info_.secure_dns_policy)) { + spdy_session_key_(using_quic_ + ? SpdySessionKey() + : GetSpdySessionKey(proxy_info_.proxy_chain(), + origin_url_, + request_info_)) { // Websocket `destination` schemes should be converted to HTTP(S). DCHECK(base::EqualsCaseInsensitiveASCII(destination_.scheme(), url::kHttpScheme) || @@ -340,10 +338,27 @@ bool HttpStreamFactory::Job::HasAvailableQuicSession() const { } bool require_dns_https_alpn = (job_type_ == DNS_ALPN_H3) || (job_type_ == PRECONNECT_DNS_ALPN_H3); + SessionUsage session_usage; + ProxyChain proxy_chain; + // TODO(https://crbug.com/1520929): Remove support for sending GET requests to + // the proxy server when proxying HTTP requests and instead always tunnel + // them. + CHECK(!proxy_info_.proxy_chain().is_multi_proxy()); + if (IsGetToProxy(proxy_info_.proxy_chain(), origin_url_)) { + session_usage = SessionUsage::kProxy; + proxy_chain = ProxyChain::Direct(); + } else { + session_usage = SessionUsage::kDestination; + proxy_chain = proxy_info_.proxy_chain(); + // TODO(https://crbug.com/1495793): Proxying QUIC over QUIC is not currently + // supported, but when it is we can remove this CHECK. + CHECK(proxy_chain.is_direct()); + } + return quic_request_.CanUseExistingSession( - origin_url_, request_info_.privacy_mode, request_info_.socket_tag, - request_info_.network_anonymization_key, request_info_.secure_dns_policy, - require_dns_https_alpn, destination_); + origin_url_, proxy_chain, request_info_.privacy_mode, session_usage, + request_info_.socket_tag, request_info_.network_anonymization_key, + request_info_.secure_dns_policy, require_dns_https_alpn, destination_); } bool HttpStreamFactory::Job::TargettedSocketGroupHasActiveSocket() const { @@ -419,7 +434,7 @@ bool HttpStreamFactory::Job::ShouldForceQuic( // If this is going through a QUIC proxy, only force QUIC for insecure // requests. If the request is secure, a tunnel will be needed, and those are // handled by the socket pools, using an HttpProxyConnectJob. - if (proxy_info.is_quic()) { + if (!proxy_info.is_direct() && proxy_info.proxy_chain().Last().is_quic()) { return !using_ssl; } return OriginToForceQuicOn(*session->context().quic_context->params(), @@ -433,10 +448,7 @@ bool HttpStreamFactory::Job::ShouldForceQuic( SpdySessionKey HttpStreamFactory::Job::GetSpdySessionKey( const ProxyChain& proxy_chain, const GURL& origin_url, - PrivacyMode privacy_mode, - const SocketTag& socket_tag, - const NetworkAnonymizationKey& network_anonymization_key, - SecureDnsPolicy secure_dns_policy) { + const HttpRequestInfo& request_info) { // In the case that we'll be sending a GET request to the proxy, look for a // HTTP/2 proxy session *to* the proxy, instead of to the origin server. The // way HTTP over HTTPS proxies work is that the ConnectJob makes a SpdyProxy, @@ -444,8 +456,7 @@ SpdySessionKey HttpStreamFactory::Job::GetSpdySessionKey( // SpdySession pool, and uses it directly (completely ignoring the result of // the ConnectJob, and in fact cancelling it). So we need to create the same // key used by the HttpProxyConnectJob for the last proxy in the chain. - if (proxy_chain.is_get_to_proxy_allowed() && proxy_chain.Last().is_https() && - origin_url.SchemeIs(url::kHttpScheme)) { + if (IsGetToProxy(proxy_chain, origin_url)) { // For this to work as expected, the whole chain should be HTTPS. for (const auto& proxy_server : proxy_chain.proxy_servers()) { CHECK(proxy_server.is_https()); @@ -453,15 +464,28 @@ SpdySessionKey HttpStreamFactory::Job::GetSpdySessionKey( auto [last_proxy_partial_chain, last_proxy_server] = proxy_chain.SplitLast(); const auto& last_proxy_host_port_pair = last_proxy_server.host_port_pair(); - return SpdySessionKey(last_proxy_host_port_pair, last_proxy_partial_chain, - PRIVACY_MODE_DISABLED, - SpdySessionKey::IsProxySession::kTrue, socket_tag, - network_anonymization_key, secure_dns_policy); + // Note that `disable_cert_network_fetches` must be true for proxies to + // avoid deadlock. See comment on + // `SSLConfig::disable_cert_verification_network_fetches`. + return SpdySessionKey( + last_proxy_host_port_pair, PRIVACY_MODE_DISABLED, + last_proxy_partial_chain, SessionUsage::kProxy, request_info.socket_tag, + request_info.network_anonymization_key, request_info.secure_dns_policy, + /*disable_cert_network_fetches=*/true); } - return SpdySessionKey(HostPortPair::FromURL(origin_url), proxy_chain, - privacy_mode, SpdySessionKey::IsProxySession::kFalse, - socket_tag, network_anonymization_key, - secure_dns_policy); + return SpdySessionKey( + HostPortPair::FromURL(origin_url), request_info.privacy_mode, proxy_chain, + SessionUsage::kDestination, request_info.socket_tag, + request_info.network_anonymization_key, request_info.secure_dns_policy, + request_info.load_flags & LOAD_DISABLE_CERT_NETWORK_FETCHES); +} + +// static +bool HttpStreamFactory::Job::IsGetToProxy(const ProxyChain& proxy_chain, + const GURL& origin_url) { + return proxy_chain.is_get_to_proxy_allowed() && + proxy_chain.Last().is_secure_http_like() && + origin_url.SchemeIs(url::kHttpScheme); } bool HttpStreamFactory::Job::CanUseExistingSpdySession() const { @@ -483,9 +507,19 @@ bool HttpStreamFactory::Job::CanUseExistingSpdySession() const { // We need to make sure that if a HTTP/2 session was created for // https://somehost/ then we do not use that session for http://somehost:443/. // The only time we can use an existing session is if the request URL is - // https (the normal case) or if we are connecting to a HTTP/2 proxy. - // https://crbug.com/133176 - return origin_url_.SchemeIs(url::kHttpsScheme) || (proxy_info_.is_https()); + // https (the normal case) or if we are connecting to an HTTPS proxy to make + // a GET request for an HTTP destination. https://crbug.com/133176 + if (origin_url_.SchemeIs(url::kHttpsScheme)) { + return true; + } + if (!proxy_info_.is_empty()) { + const ProxyChain& proxy_chain = proxy_info_.proxy_chain(); + if (!proxy_chain.is_direct() && proxy_chain.is_get_to_proxy_allowed() && + proxy_chain.Last().is_https()) { + return true; + } + } + return false; } void HttpStreamFactory::Job::OnStreamReadyCallback() { @@ -718,7 +752,9 @@ int HttpStreamFactory::Job::DoStart() { } if (!session_->params().enable_quic_proxies_for_https_urls && - proxy_info_.is_quic() && request_info_.url.SchemeIsCryptographic()) { + !proxy_info_.is_empty() && !proxy_info_.is_direct() && + proxy_info_.proxy_chain().Last().is_quic() && + request_info_.url.SchemeIsCryptographic()) { return ERR_NOT_IMPLEMENTED; } @@ -768,7 +804,8 @@ int HttpStreamFactory::Job::DoInitConnection() { int HttpStreamFactory::Job::DoInitConnectionImpl() { DCHECK(!connection_->is_initialized()); - if (using_quic_ && !proxy_info_.is_quic() && !proxy_info_.is_direct()) { + if (using_quic_ && !proxy_info_.is_direct() && + !proxy_info_.proxy_chain().Last().is_quic()) { // QUIC can not be spoken to non-QUIC proxies. This error should not be // user visible, because the non-alternative Job should be resumed. return ERR_NO_SUPPORTED_PROXIES; @@ -787,9 +824,6 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { return DoInitConnectionImplQuic(server_ssl_config.GetCertVerifyFlags()); } - SSLConfig server_ssl_config; - server_ssl_config.allowed_bad_certs = allowed_bad_certs_; - // Check first if there is a pushed stream matching the request, or an HTTP/2 // connection this request can pool to. If so, then go straight to using // that. @@ -848,9 +882,7 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { } } - if (proxy_info_.is_http_like()) { - establishing_tunnel_ = !UsingHttpProxyWithoutTunnel(); - } + establishing_tunnel_ = !UsingHttpProxyWithoutTunnel(); if (job_type_ == PRECONNECT) { DCHECK(!is_websocket_); @@ -864,7 +896,7 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { return PreconnectSocketsForHttpRequest( destination_, request_info_.load_flags, priority_, session_, - proxy_info_, server_ssl_config, request_info_.privacy_mode, + proxy_info_, allowed_bad_certs_, request_info_.privacy_mode, request_info_.network_anonymization_key, request_info_.secure_dns_policy, net_log_, num_streams_, std::move(callback)); @@ -878,14 +910,14 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() { DCHECK_EQ(SecureDnsPolicy::kAllow, request_info_.secure_dns_policy); return InitSocketHandleForWebSocketRequest( destination_, request_info_.load_flags, priority_, session_, - proxy_info_, server_ssl_config, request_info_.privacy_mode, + proxy_info_, allowed_bad_certs_, request_info_.privacy_mode, request_info_.network_anonymization_key, net_log_, connection_.get(), io_callback_, proxy_auth_callback); } return InitSocketHandleForHttpRequest( destination_, request_info_.load_flags, priority_, session_, proxy_info_, - server_ssl_config, request_info_.privacy_mode, + allowed_bad_certs_, request_info_.privacy_mode, request_info_.network_anonymization_key, request_info_.secure_dns_policy, request_info_.socket_tag, net_log_, connection_.get(), io_callback_, proxy_auth_callback); @@ -896,7 +928,11 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic( url::SchemeHostPort destination; GURL url(request_info_.url); int cert_verifier_flags; - if (proxy_info_.is_quic()) { + SessionUsage session_usage; + + if (!proxy_info_.is_empty() && !proxy_info_.is_direct() && + proxy_info_.proxy_chain().Last().is_quic()) { + DCHECK(url.SchemeIs(url::kHttpScheme)); // Disable network fetches for QUIC proxies, since the network requests // are probably going to need to go through the proxy chain too. // @@ -904,29 +940,39 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic( // proxies in ConnectJobFactory. cert_verifier_flags = CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES; - // TODO(https://crbug.com/1491092): Update this to support proxy chains with - // multiple proxies and add tests. + // TODO(https://crbug.com/1520929): Remove support for sending GET requests + // to the proxy server when proxying HTTP requests and instead always tunnel + // them. CHECK(!proxy_info_.proxy_chain().is_multi_proxy()); const HostPortPair& proxy_endpoint = proxy_info_.proxy_chain().Last().host_port_pair(); destination = url::SchemeHostPort(url::kHttpsScheme, proxy_endpoint.host(), proxy_endpoint.port()); url = destination.GetURL(); + session_usage = SessionUsage::kProxy; } else { DCHECK(using_ssl_); destination = destination_; cert_verifier_flags = server_cert_verifier_flags; + // This connection is to the destination and not to an intermediate proxy. + session_usage = SessionUsage::kDestination; } DCHECK(url.SchemeIs(url::kHttpsScheme)); bool require_dns_https_alpn = (job_type_ == DNS_ALPN_H3) || (job_type_ == PRECONNECT_DNS_ALPN_H3); + absl::optional traffic_annotation = + proxy_info_.traffic_annotation().is_valid() + ? absl::make_optional( + proxy_info_.traffic_annotation()) + : absl::nullopt; int rv = quic_request_.Request( - std::move(destination), quic_version_, request_info_.privacy_mode, + std::move(destination), quic_version_, ProxyChain::Direct(), + std::move(traffic_annotation), session_usage, request_info_.privacy_mode, priority_, request_info_.socket_tag, request_info_.network_anonymization_key, request_info_.secure_dns_policy, - proxy_info_.is_direct(), require_dns_https_alpn, cert_verifier_flags, url, - net_log_, &net_error_details_, + require_dns_https_alpn, cert_verifier_flags, url, net_log_, + &net_error_details_, base::BindOnce(&Job::OnFailedOnDefaultNetwork, ptr_factory_.GetWeakPtr()), io_callback_); if (rv == OK) { @@ -936,6 +982,9 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic( // delay the main job. delegate_->MaybeSetWaitTimeForMainJob( quic_request_.GetTimeDelayForWaitingJob()); + // Set up to get notified of either host resolution completion or session + // creation, in order to call the delegate's `OnConnectionInitialized` + // callback. expect_on_quic_host_resolution_ = quic_request_.WaitForHostResolution( base::BindOnce(&Job::OnQuicHostResolution, base::Unretained(this))); expect_on_quic_session_created_ = quic_request_.WaitForQuicSessionCreation( @@ -944,20 +993,25 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic( return rv; } +void HttpStreamFactory::Job::OnQuicHostResolution(int result) { + DCHECK(expect_on_quic_host_resolution_); + expect_on_quic_host_resolution_ = false; + // If no `OnQuicSessionCreated` call is expected, then consider the + // connection "initialized" and inform the delegate. Note that + // `OnQuicHostResolution` is actually called somewhat _after_ host resolution + // is complete -- the `Job` has already run to the point where it can make no + // further progress. + if (!expect_on_quic_session_created_) { + delegate_->OnConnectionInitialized(this, result); + } +} + void HttpStreamFactory::Job::OnQuicSessionCreated(int result) { DCHECK(expect_on_quic_session_created_); expect_on_quic_session_created_ = false; delegate_->OnConnectionInitialized(this, result); } -void HttpStreamFactory::Job::OnQuicHostResolution(int result) { - DCHECK(expect_on_quic_host_resolution_); - expect_on_quic_host_resolution_ = false; - if (!expect_on_quic_session_created_) { - delegate_->OnConnectionInitialized(this, result); - } -} - void HttpStreamFactory::Job::OnFailedOnDefaultNetwork(int result) { DCHECK(job_type_ == ALTERNATIVE || job_type_ == DNS_ALPN_H3); DCHECK(using_quic_); @@ -1004,8 +1058,12 @@ int HttpStreamFactory::Job::DoInitConnectionComplete(int result) { } } else if (connection_->socket()->GetNegotiatedProtocol() != kProtoUnknown) { - // Only connections that use TLS can negotiate ALPN. - DCHECK(using_ssl_ || proxy_info_.is_secure_http_like()); + // Only connections that use TLS (either to the origin or via a GET to a + // secure proxy) can negotiate ALPN. + bool get_to_secure_proxy = + IsGetToProxy(proxy_info_.proxy_chain(), origin_url_) && + proxy_info_.proxy_chain().Last().is_secure_http_like(); + DCHECK(using_ssl_ || get_to_secure_proxy); negotiated_protocol_ = connection_->socket()->GetNegotiatedProtocol(); net_log_.AddEvent(NetLogEventType::HTTP_STREAM_REQUEST_PROTO, [&] { return NetLogHttpStreamProtoParams(negotiated_protocol_); @@ -1028,7 +1086,8 @@ int HttpStreamFactory::Job::DoInitConnectionComplete(int result) { } } - if (proxy_info_.is_quic() && using_quic_ && result < 0) { + if (using_quic_ && result < 0 && !proxy_info_.is_direct() && + proxy_info_.proxy_chain().Last().is_quic()) { return ReconsiderProxyAfterError(result); } diff --git a/naiveproxy/src/net/http/http_stream_factory_job.h b/naiveproxy/src/net/http/http_stream_factory_job.h index 76961618f4..2fe9fe1b3d 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job.h +++ b/naiveproxy/src/net/http/http_stream_factory_job.h @@ -32,6 +32,7 @@ #include "net/spdy/spdy_session_key.h" #include "net/spdy/spdy_session_pool.h" #include "net/ssl/ssl_config.h" +#include "url/gurl.h" #include "url/scheme_host_port.h" namespace net { @@ -113,7 +114,9 @@ class HttpStreamFactory::Job Job* job, const ConnectionAttempts& attempts) = 0; - // Invoked when |job| finishes initiating a connection. + // Invoked when |job| finishes initiating a connection. This may occur + // before the handshake is complete, and provides the delegate an + // early chance to handle any errors. virtual void OnConnectionInitialized(Job* job, int rv) = 0; // Return false if |job| can advance to the next state. Otherwise, |job| @@ -340,13 +343,20 @@ class HttpStreamFactory::Job bool is_websocket); // Called in Job constructor. Use |spdy_session_key_| after construction. - static SpdySessionKey GetSpdySessionKey( - const ProxyChain& proxy_chain, - const GURL& origin_url, - PrivacyMode privacy_mode, - const SocketTag& socket_tag, - const NetworkAnonymizationKey& network_anonymization_key, - SecureDnsPolicy secure_dns_policy); + static SpdySessionKey GetSpdySessionKey(const ProxyChain& proxy_chain, + const GURL& origin_url, + const HttpRequestInfo& request_info); + + // Returns whether an appropriate SPDY or QUIC session would correspond to + // either a connection to the last proxy server in the chain (for the + // traditional HTTP proxying behavior of sending a GET request to the proxy + // server) or a connection through the entire proxy chain (for tunneled + // requests). + // TODO(https://crbug.com/1495793): Support for this is being removed for QUIC + // proxy chains, but will remain for SPDY proxies (so update the comment + // above once this change is made). + static bool IsGetToProxy(const ProxyChain& proxy_chain, + const GURL& origin_url); // Returns true if the current request can use an existing spdy session. bool CanUseExistingSpdySession() const; diff --git a/naiveproxy/src/net/http/http_stream_factory_job_controller.cc b/naiveproxy/src/net/http/http_stream_factory_job_controller.cc index 57c6aa465d..c140fb5f1d 100644 --- a/naiveproxy/src/net/http/http_stream_factory_job_controller.cc +++ b/naiveproxy/src/net/http/http_stream_factory_job_controller.cc @@ -21,6 +21,7 @@ #include "net/base/privacy_mode.h" #include "net/base/proxy_chain.h" #include "net/base/proxy_string_util.h" +#include "net/base/session_usage.h" #include "net/base/url_util.h" #include "net/http/bidirectional_stream_impl.h" #include "net/http/transport_security_state.h" @@ -29,6 +30,7 @@ #include "net/log/net_log_with_source.h" #include "net/proxy_resolution/proxy_resolution_request.h" #include "net/proxy_resolution/proxy_resolution_service.h" +#include "net/quic/quic_session_key.h" #include "net/spdy/spdy_session.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -89,9 +91,7 @@ void HistogramProxyUsed(const ProxyInfo& proxy_info, bool success) { } proxy_scheme = proxy_info.proxy_chain().is_direct() ? static_cast(1) - : proxy_info.proxy_chain() - .GetProxyServer(/*chain_index=*/0) - .scheme(); + : proxy_info.proxy_chain().First().scheme(); } if (success) { UMA_HISTOGRAM_ENUMERATION("Net.HttpJob.ProxyTypeSuccess", proxy_scheme, @@ -1296,8 +1296,10 @@ HttpStreamFactory::JobController::GetAlternativeServiceInfoInternal( // Check whether there is an existing QUIC session to use for this origin. GURL mapped_origin = original_url; RewriteUrlWithHostMappingRules(mapped_origin); + CHECK(proxy_info_.proxy_chain().is_direct()); QuicSessionKey session_key( HostPortPair::FromURL(mapped_origin), request_info.privacy_mode, + proxy_info_.proxy_chain(), SessionUsage::kDestination, request_info.socket_tag, request_info.network_anonymization_key, request_info.secure_dns_policy, /*require_dns_https_alpn=*/false); @@ -1402,13 +1404,15 @@ int HttpStreamFactory::JobController::ReconsiderProxyAfterError(Job* job, return error; } - if (proxy_info_.is_secure_http_like()) { - // TODO(https://crbug.com/1491092): Should do this for every proxy in the - // chain as part of adding support for client certificates. - session_->ssl_client_context()->ClearClientCertificate( - proxy_info_.proxy_chain() - .GetProxyServer(/*chain_index=*/0) - .host_port_pair()); + // Clear client certificates for all proxies in the chain. + // TODO(https://crbug.com/1491092): client certificates for multi-proxy + // chains are not yet supported, and this is only tested with single-proxy + // chains. + for (auto& proxy_server : proxy_info_.proxy_chain().proxy_servers()) { + if (proxy_server.is_secure_http_like()) { + session_->ssl_client_context()->ClearClientCertificate( + proxy_server.host_port_pair()); + } } if (!proxy_info_.Fallback(error, net_log_)) { diff --git a/naiveproxy/src/net/http/http_stream_parser.cc b/naiveproxy/src/net/http/http_stream_parser.cc index 092d730d49..7e4e185385 100644 --- a/naiveproxy/src/net/http/http_stream_parser.cc +++ b/naiveproxy/src/net/http/http_stream_parser.cc @@ -16,6 +16,7 @@ #include "base/numerics/clamped_math.h" #include "base/strings/string_util.h" #include "base/values.h" +#include "net/base/features.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/upload_data_stream.h" @@ -187,7 +188,9 @@ HttpStreamParser::HttpStreamParser(StreamSocket* stream_socket, response_header_start_offset_(std::string::npos), stream_socket_(stream_socket), connection_is_reused_(connection_is_reused), - net_log_(net_log) { + net_log_(net_log), + truncate_to_content_length_enabled_(base::FeatureList::IsEnabled( + net::features::kTruncateBodyToContentLength)) { io_callback_ = base::BindRepeating(&HttpStreamParser::OnIOComplete, weak_ptr_factory_.GetWeakPtr()); } @@ -645,17 +648,35 @@ int HttpStreamParser::DoReadBody() { // Added to investigate crbug.com/499663. CHECK(user_read_buf_.get()); + // There may be additional data after the end of the body waiting in + // the socket, but in order to find out, we need to read as much as possible. + // If there is additional data, discard it and close the connection later. + int64_t remaining_read_len = user_read_buf_len_; + int64_t remaining_body = 0; + if (truncate_to_content_length_enabled_ && !chunked_decoder_.get() && + response_body_length_ >= 0) { + remaining_body = response_body_length_ - response_body_read_; + remaining_read_len = std::min(remaining_read_len, remaining_body); + } + // There may be some data left over from reading the response headers. if (read_buf_->offset()) { - int available = read_buf_->offset() - read_buf_unused_offset_; + int64_t available = read_buf_->offset() - read_buf_unused_offset_; if (available) { CHECK_GT(available, 0); - int bytes_from_buffer = std::min(available, user_read_buf_len_); + int64_t bytes_from_buffer = std::min(available, remaining_read_len); memcpy(user_read_buf_->data(), read_buf_->StartOfBuffer() + read_buf_unused_offset_, bytes_from_buffer); read_buf_unused_offset_ += bytes_from_buffer; - if (bytes_from_buffer == available) { + // Clear out the remaining data if we've reached the end of the body. + if (truncate_to_content_length_enabled_ && + (remaining_body == bytes_from_buffer) && + (available > bytes_from_buffer)) { + read_buf_->SetCapacity(0); + read_buf_unused_offset_ = 0; + discarded_extra_data_ = true; + } else if (bytes_from_buffer == available) { read_buf_->SetCapacity(0); read_buf_unused_offset_ = 0; } @@ -670,12 +691,31 @@ int HttpStreamParser::DoReadBody() { if (IsResponseBodyComplete()) return 0; + // DoReadBodyComplete will truncate the amount read if necessary whether the + // read completes synchronously or asynchronously. DCHECK_EQ(0, read_buf_->offset()); return stream_socket_->Read(user_read_buf_.get(), user_read_buf_len_, io_callback_); } int HttpStreamParser::DoReadBodyComplete(int result) { + // Check to see if we've read too much and need to discard data before we + // increment received_bytes_ and response_body_read_ or otherwise start + // processing the data. + if (truncate_to_content_length_enabled_ && !chunked_decoder_.get() && + response_body_length_ >= 0) { + // Calculate how much we should have been allowed to read to not go beyond + // the Content-Length. + int64_t remaining_body = response_body_length_ - response_body_read_; + int64_t remaining_read_len = + std::min(static_cast(user_read_buf_len_), remaining_body); + if (result > remaining_read_len) { + // Truncate to only what is in the body. + result = remaining_read_len; + discarded_extra_data_ = true; + } + } + // When the connection is closed, there are numerous ways to interpret it. // // - If a Content-Length header is present and the body contains exactly that @@ -1126,8 +1166,10 @@ bool HttpStreamParser::CanReuseConnection() const { // // TODO(mmenke): Consider logging this - hard to decipher socket reuse // behavior makes NetLogs harder to read. - if (IsResponseBodyComplete() && IsMoreDataBuffered()) + if ((IsResponseBodyComplete() && IsMoreDataBuffered()) || + discarded_extra_data_) { return false; + } return stream_socket_->IsConnected(); } diff --git a/naiveproxy/src/net/http/http_stream_parser.h b/naiveproxy/src/net/http/http_stream_parser.h index c8e5612404..d874adccab 100644 --- a/naiveproxy/src/net/http/http_stream_parser.h +++ b/naiveproxy/src/net/http/http_stream_parser.h @@ -319,6 +319,12 @@ class NET_EXPORT_PRIVATE HttpStreamParser { scoped_refptr request_body_send_buf_; bool sent_last_chunk_ = false; + // Whether the Content-Length was known and extra data was discarded. + bool discarded_extra_data_ = false; + + // Whether the response body should be truncated to the Content-Length. + const bool truncate_to_content_length_enabled_; + // Error received when uploading the body, if any. int upload_error_ = OK; diff --git a/naiveproxy/src/net/http/http_transaction_test_util.cc b/naiveproxy/src/net/http/http_transaction_test_util.cc index a1d296f44e..2264be8806 100644 --- a/naiveproxy/src/net/http/http_transaction_test_util.cc +++ b/naiveproxy/src/net/http/http_transaction_test_util.cc @@ -65,8 +65,8 @@ const MockTransaction kSimpleGET_Transaction = { base::Time(), "Google Blah Blah", {}, - absl::nullopt, - absl::nullopt, + std::nullopt, + std::nullopt, TEST_MODE_NORMAL, MockTransactionHandler(), MockTransactionReadHandler(), @@ -89,8 +89,8 @@ const MockTransaction kSimplePOST_Transaction = { base::Time(), "Google Blah Blah", {}, - absl::nullopt, - absl::nullopt, + std::nullopt, + std::nullopt, TEST_MODE_NORMAL, MockTransactionHandler(), MockTransactionReadHandler(), @@ -114,8 +114,8 @@ const MockTransaction kTypicalGET_Transaction = { base::Time(), "Google Blah Blah", {}, - absl::nullopt, - absl::nullopt, + std::nullopt, + std::nullopt, TEST_MODE_NORMAL, MockTransactionHandler(), MockTransactionReadHandler(), @@ -139,8 +139,8 @@ const MockTransaction kETagGET_Transaction = { base::Time(), "Google Blah Blah", {}, - absl::nullopt, - absl::nullopt, + std::nullopt, + std::nullopt, TEST_MODE_NORMAL, MockTransactionHandler(), MockTransactionReadHandler(), @@ -163,8 +163,8 @@ const MockTransaction kRangeGET_Transaction = { base::Time(), "Google Blah Blah", {}, - absl::nullopt, - absl::nullopt, + std::nullopt, + std::nullopt, TEST_MODE_NORMAL, MockTransactionHandler(), MockTransactionReadHandler(), diff --git a/naiveproxy/src/net/http/http_transaction_test_util.h b/naiveproxy/src/net/http/http_transaction_test_util.h index 80e69582e0..42d99dabc8 100644 --- a/naiveproxy/src/net/http/http_transaction_test_util.h +++ b/naiveproxy/src/net/http/http_transaction_test_util.h @@ -5,17 +5,16 @@ #ifndef NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ #define NET_HTTP_HTTP_TRANSACTION_TEST_UTIL_H_ -#include "base/memory/raw_ptr.h" -#include "net/http/http_transaction.h" - #include +#include #include #include #include #include "base/compiler_specific.h" #include "base/functional/callback.h" +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" @@ -33,9 +32,9 @@ #include "net/http/http_request_info.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" +#include "net/http/http_transaction.h" #include "net/log/net_log_source.h" #include "net/socket/connection_attempts.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -92,8 +91,8 @@ struct MockTransaction { // known aliases, e.g. from A, AAAA, or HTTPS, not just from the address used // for the connection, in no particular order. std::set dns_aliases; - absl::optional fps_cache_filter; - absl::optional browser_run_id; + std::optional fps_cache_filter; + std::optional browser_run_id; int test_mode; MockTransactionHandler handler; MockTransactionReadHandler read_handler; diff --git a/naiveproxy/src/net/http/proxy_fallback.cc b/naiveproxy/src/net/http/proxy_fallback.cc index f65dcbd45b..c4f74b59a0 100644 --- a/naiveproxy/src/net/http/proxy_fallback.cc +++ b/naiveproxy/src/net/http/proxy_fallback.cc @@ -15,15 +15,15 @@ NET_EXPORT bool CanFalloverToNextProxy(const ProxyChain& proxy_chain, int* final_error, bool is_for_ip_protection) { *final_error = error; - - if (!proxy_chain.is_direct() && - proxy_chain.GetProxyServer(/*chain_index=*/0).is_quic()) { - // TODO(https://crbug.com/1495793): For supporting QUIC with proxy chains - // containing more than one proxy server it's unclear whether the proxy - // server at chain index 0 is really what we should be doing here. Figure - // that out and add tests. - CHECK(!proxy_chain.is_multi_proxy()); - + auto proxy_servers = proxy_chain.proxy_servers(); + bool has_quic_proxy = std::any_of( + proxy_servers.begin(), proxy_servers.end(), + [](const ProxyServer& proxy_server) { return proxy_server.is_quic(); }); + if (!proxy_chain.is_direct() && has_quic_proxy) { + // The whole chain should be QUIC. + for (const auto& proxy_server : proxy_servers) { + CHECK(proxy_server.is_quic()); + } switch (error) { case ERR_QUIC_PROTOCOL_ERROR: case ERR_QUIC_HANDSHAKE_FAILED: diff --git a/naiveproxy/src/net/http/structured_headers.h b/naiveproxy/src/net/http/structured_headers.h index 77c7a24c78..eee38aee66 100644 --- a/naiveproxy/src/net/http/structured_headers.h +++ b/naiveproxy/src/net/http/structured_headers.h @@ -5,11 +5,11 @@ #ifndef NET_HTTP_STRUCTURED_HEADERS_H_ #define NET_HTTP_STRUCTURED_HEADERS_H_ +#include #include #include "base/strings/string_piece.h" #include "net/third_party/quiche/src/quiche/common/structured_headers.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net::structured_headers { @@ -25,38 +25,37 @@ using ListOfLists = quiche::structured_headers::ListOfLists; using List = quiche::structured_headers::List; using Parameters = quiche::structured_headers::Parameters; -inline absl::optional ParseItem(base::StringPiece str) { +inline std::optional ParseItem(base::StringPiece str) { return quiche::structured_headers::ParseItem(str); } -inline absl::optional ParseBareItem(base::StringPiece str) { +inline std::optional ParseBareItem(base::StringPiece str) { return quiche::structured_headers::ParseBareItem(str); } -inline absl::optional ParseParameterisedList( +inline std::optional ParseParameterisedList( base::StringPiece str) { return quiche::structured_headers::ParseParameterisedList(str); } -inline absl::optional ParseListOfLists(base::StringPiece str) { +inline std::optional ParseListOfLists(base::StringPiece str) { return quiche::structured_headers::ParseListOfLists(str); } -inline absl::optional ParseList(base::StringPiece str) { +inline std::optional ParseList(base::StringPiece str) { return quiche::structured_headers::ParseList(str); } -inline absl::optional ParseDictionary(base::StringPiece str) { +inline std::optional ParseDictionary(base::StringPiece str) { return quiche::structured_headers::ParseDictionary(str); } -inline absl::optional SerializeItem(const Item& value) { +inline std::optional SerializeItem(const Item& value) { return quiche::structured_headers::SerializeItem(value); } -inline absl::optional SerializeItem( +inline std::optional SerializeItem( const ParameterizedItem& value) { return quiche::structured_headers::SerializeItem(value); } -inline absl::optional SerializeList(const List& value) { +inline std::optional SerializeList(const List& value) { return quiche::structured_headers::SerializeList(value); } -inline absl::optional SerializeDictionary( - const Dictionary& value) { +inline std::optional SerializeDictionary(const Dictionary& value) { return quiche::structured_headers::SerializeDictionary(value); } diff --git a/naiveproxy/src/net/http/transport_security_persister.cc b/naiveproxy/src/net/http/transport_security_persister.cc index 264e0109b6..c75538d667 100644 --- a/naiveproxy/src/net/http/transport_security_persister.cc +++ b/naiveproxy/src/net/http/transport_security_persister.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -26,7 +27,6 @@ #include "net/base/network_anonymization_key.h" #include "net/cert/x509_certificate.h" #include "net/http/transport_security_state.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -41,12 +41,12 @@ std::string HashedDomainToExternalString( // This inverts |HashedDomainToExternalString|, above. It turns an external // string (from a JSON file) into an internal (binary) array. -absl::optional ExternalStringToHashedDomain( +std::optional ExternalStringToHashedDomain( const std::string& external) { TransportSecurityState::HashedHost out; - absl::optional> hashed = base::Base64Decode(external); + std::optional> hashed = base::Base64Decode(external); if (!hashed.has_value() || hashed.value().size() != out.size()) { - return absl::nullopt; + return std::nullopt; } std::copy_n(hashed.value().begin(), out.size(), out.begin()); @@ -135,10 +135,10 @@ void DeserializeSTSData(const base::Value& sts_list, continue; const std::string* hostname = sts_dict->FindString(kHostname); - absl::optional sts_include_subdomains = + std::optional sts_include_subdomains = sts_dict->FindBool(kStsIncludeSubdomains); - absl::optional sts_observed = sts_dict->FindDouble(kStsObserved); - absl::optional expiry = sts_dict->FindDouble(kExpiry); + std::optional sts_observed = sts_dict->FindDouble(kStsObserved); + std::optional expiry = sts_dict->FindDouble(kExpiry); const std::string* mode = sts_dict->FindString(kMode); if (!hostname || !sts_include_subdomains.has_value() || @@ -164,7 +164,7 @@ void DeserializeSTSData(const base::Value& sts_list, if (sts_state.expiry < current_time || !sts_state.ShouldUpgradeToSSL()) continue; - absl::optional hashed = + std::optional hashed = ExternalStringToHashedDomain(*hostname); if (!hashed.has_value()) continue; @@ -224,7 +224,7 @@ void TransportSecurityPersister::WriteNow(TransportSecurityState* state, &OnWriteFinishedTask, foreground_runner_, base::BindOnce(&TransportSecurityPersister::OnWriteFinished, weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); - absl::optional data = SerializeData(); + std::optional data = SerializeData(); if (data) { writer_.WriteNow(std::move(data).value()); } else { @@ -237,7 +237,7 @@ void TransportSecurityPersister::OnWriteFinished(base::OnceClosure callback) { std::move(callback).Run(); } -absl::optional TransportSecurityPersister::SerializeData() { +std::optional TransportSecurityPersister::SerializeData() { CHECK(foreground_runner_->RunsTasksInCurrentSequence()); base::Value::Dict toplevel; @@ -246,7 +246,7 @@ absl::optional TransportSecurityPersister::SerializeData() { std::string output; if (!base::JSONWriter::Write(toplevel, &output)) { - return absl::nullopt; + return std::nullopt; } return output; } @@ -267,12 +267,12 @@ void TransportSecurityPersister::Deserialize( const std::string& serialized, TransportSecurityState* state, bool& contains_legacy_expect_ct_data) { - absl::optional value = base::JSONReader::Read(serialized); + std::optional value = base::JSONReader::Read(serialized); if (!value || !value->is_dict()) return; base::Value::Dict& dict = value->GetDict(); - absl::optional version = dict.FindInt(kVersionKey); + std::optional version = dict.FindInt(kVersionKey); // Stop if the data is out of date (or in the previous format that didn't have // a version number). diff --git a/naiveproxy/src/net/http/transport_security_persister.h b/naiveproxy/src/net/http/transport_security_persister.h index 3a7c3458fa..96033d971c 100644 --- a/naiveproxy/src/net/http/transport_security_persister.h +++ b/naiveproxy/src/net/http/transport_security_persister.h @@ -33,6 +33,7 @@ #ifndef NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_ #define NET_HTTP_TRANSPORT_SECURITY_PERSISTER_H_ +#include #include #include "base/files/file_path.h" @@ -42,7 +43,6 @@ #include "base/memory/weak_ptr.h" #include "net/base/net_export.h" #include "net/http/transport_security_state.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class SequencedTaskRunner; @@ -113,7 +113,7 @@ class NET_EXPORT TransportSecurityPersister // The reason for hashing them is so that the stored state does not // trivially reveal a user's browsing history to an attacker reading the // serialized state on disk. - absl::optional SerializeData() override; + std::optional SerializeData() override; // Clears any existing non-static entries, and then re-populates // |transport_security_state_|. diff --git a/naiveproxy/src/net/http/transport_security_state.cc b/naiveproxy/src/net/http/transport_security_state.cc index 3cd3f711e3..3f5400099c 100644 --- a/naiveproxy/src/net/http/transport_security_state.cc +++ b/naiveproxy/src/net/http/transport_security_state.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include "net/http/http_security_headers.h" #include "net/net_buildflags.h" #include "net/ssl/ssl_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -94,7 +94,7 @@ std::vector CanonicalizeHost(const std::string& host) { // invalid characters in the host (via DNSDomainFromDot()). std::string lowered_host = base::ToLowerASCII(host); - absl::optional> new_host = + std::optional> new_host = dns_names_util::DottedNameToNetwork( lowered_host, /*require_valid_internet_hostname=*/true); @@ -385,8 +385,8 @@ void TransportSecurityState::UpdatePinList( // entry, we will ignore that particular pin. continue; } - host_pins_.value()[pin.hostname_] = std::make_pair( - pinset_names_map[pin.pinset_name_], pin.include_subdomains_); + host_pins_.value()[pin.hostname_] = + std::pair(pinset_names_map[pin.pinset_name_], pin.include_subdomains_); } } @@ -772,7 +772,7 @@ bool TransportSecurityState::GetDynamicSTSState(const std::string& host, // An entry matches if it is either an exact match, or if it is a prefix // match and the includeSubDomains directive was included. if (i == 0 || j->second.include_subdomains) { - absl::optional dotted_name = + std::optional dotted_name = dns_names_util::NetworkToDottedName(host_sub_chunk); if (!dotted_name) return false; @@ -818,7 +818,7 @@ bool TransportSecurityState::GetDynamicPKPState(const std::string& host, // implement HPKP, so this logic is only used via AddHPKP(), reachable from // Cronet. if (i == 0 || j->second.include_subdomains) { - absl::optional dotted_name = + std::optional dotted_name = dns_names_util::NetworkToDottedName(host_sub_chunk); if (!dotted_name) return false; diff --git a/naiveproxy/src/net/http/transport_security_state.h b/naiveproxy/src/net/http/transport_security_state.h index b2d0858145..cc4c8509fa 100644 --- a/naiveproxy/src/net/http/transport_security_state.h +++ b/naiveproxy/src/net/http/transport_security_state.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -28,7 +29,6 @@ #include "net/cert/signed_certificate_timestamp_and_status.h" #include "net/http/transport_security_state_source.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -522,7 +522,7 @@ class NET_EXPORT TransportSecurityState { // The values in host_pins_ maps are references to PinSet objects in the // pinsets_ vector. - absl::optional< + std::optional< std::map, std::less<>>> host_pins_; base::Time key_pins_list_last_update_time_; diff --git a/naiveproxy/src/net/http/transport_security_state_static.pins b/naiveproxy/src/net/http/transport_security_state_static.pins index 270aeb5642..5bd4be8e35 100644 --- a/naiveproxy/src/net/http/transport_security_state_static.pins +++ b/naiveproxy/src/net/http/transport_security_state_static.pins @@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2024-02-11 12:56 UTC +# Last updated: 2024-03-11 12:55 UTC PinsListTimestamp -1707656178 +1710161732 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= diff --git a/naiveproxy/src/net/http/transport_security_state_static_pins.json b/naiveproxy/src/net/http/transport_security_state_static_pins.json index ca31e26a1f..08aa3c0edd 100644 --- a/naiveproxy/src/net/http/transport_security_state_static_pins.json +++ b/naiveproxy/src/net/http/transport_security_state_static_pins.json @@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2024-02-11 12:56 UTC +// Last updated: 2024-03-11 12:55 UTC // { "pinsets": [ diff --git a/naiveproxy/src/net/log/file_net_log_observer.cc b/naiveproxy/src/net/log/file_net_log_observer.cc index 45ffa438c9..95b88bb63f 100644 --- a/naiveproxy/src/net/log/file_net_log_observer.cc +++ b/naiveproxy/src/net/log/file_net_log_observer.cc @@ -201,7 +201,7 @@ class FileNetLogObserver::FileWriter { // If max_event_file_size == kNoLimit, then no limit is enforced. FileWriter(const base::FilePath& log_path, const base::FilePath& inprogress_dir_path, - absl::optional pre_existing_log_file, + std::optional pre_existing_log_file, uint64_t max_event_file_size, size_t total_num_event_files, scoped_refptr task_runner); @@ -338,7 +338,7 @@ std::unique_ptr FileNetLogObserver::CreateBounded( NetLogCaptureMode capture_mode, std::unique_ptr constants) { return CreateInternal(log_path, SiblingInprogressDirectory(log_path), - absl::nullopt, max_total_size, kDefaultNumFiles, + std::nullopt, max_total_size, kDefaultNumFiles, capture_mode, std::move(constants)); } @@ -346,7 +346,7 @@ std::unique_ptr FileNetLogObserver::CreateUnbounded( const base::FilePath& log_path, NetLogCaptureMode capture_mode, std::unique_ptr constants) { - return CreateInternal(log_path, base::FilePath(), absl::nullopt, kNoLimit, + return CreateInternal(log_path, base::FilePath(), std::nullopt, kNoLimit, kDefaultNumFiles, capture_mode, std::move(constants)); } @@ -358,7 +358,7 @@ FileNetLogObserver::CreateBoundedPreExisting( NetLogCaptureMode capture_mode, std::unique_ptr constants) { return CreateInternal(base::FilePath(), inprogress_dir_path, - absl::make_optional(std::move(output_file)), + std::make_optional(std::move(output_file)), max_total_size, kDefaultNumFiles, capture_mode, std::move(constants)); } @@ -369,7 +369,7 @@ FileNetLogObserver::CreateUnboundedPreExisting( NetLogCaptureMode capture_mode, std::unique_ptr constants) { return CreateInternal(base::FilePath(), base::FilePath(), - absl::make_optional(std::move(output_file)), + std::make_optional(std::move(output_file)), kNoLimit, kDefaultNumFiles, capture_mode, std::move(constants)); } @@ -435,14 +435,14 @@ std::unique_ptr FileNetLogObserver::CreateBoundedForTests( NetLogCaptureMode capture_mode, std::unique_ptr constants) { return CreateInternal(log_path, SiblingInprogressDirectory(log_path), - absl::nullopt, max_total_size, total_num_event_files, + std::nullopt, max_total_size, total_num_event_files, capture_mode, std::move(constants)); } std::unique_ptr FileNetLogObserver::CreateInternal( const base::FilePath& log_path, const base::FilePath& inprogress_dir_path, - absl::optional pre_existing_log_file, + std::optional pre_existing_log_file, uint64_t max_total_size, size_t total_num_event_files, NetLogCaptureMode capture_mode, @@ -547,7 +547,7 @@ FileNetLogObserver::WriteQueue::~WriteQueue() = default; FileNetLogObserver::FileWriter::FileWriter( const base::FilePath& log_path, const base::FilePath& inprogress_dir_path, - absl::optional pre_existing_log_file, + std::optional pre_existing_log_file, uint64_t max_event_file_size, size_t total_num_event_files, scoped_refptr task_runner) diff --git a/naiveproxy/src/net/log/file_net_log_observer.h b/naiveproxy/src/net/log/file_net_log_observer.h index cba23907f0..5ae249a4b6 100644 --- a/naiveproxy/src/net/log/file_net_log_observer.h +++ b/naiveproxy/src/net/log/file_net_log_observer.h @@ -7,6 +7,7 @@ #include #include +#include #include "base/files/file.h" #include "base/functional/callback.h" @@ -14,7 +15,6 @@ #include "base/values.h" #include "net/base/net_export.h" #include "net/log/net_log.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class FilePath; @@ -130,7 +130,7 @@ class NET_EXPORT FileNetLogObserver : public NetLog::ThreadSafeObserver { static std::unique_ptr CreateInternal( const base::FilePath& log_path, const base::FilePath& inprogress_dir_path, - absl::optional pre_existing_out_file, + std::optional pre_existing_out_file, uint64_t max_total_size, size_t total_num_event_files, NetLogCaptureMode capture_mode, diff --git a/naiveproxy/src/net/log/net_log_event_type_list.h b/naiveproxy/src/net/log/net_log_event_type_list.h index 40be0f5cad..8275b133bb 100644 --- a/naiveproxy/src/net/log/net_log_event_type_list.h +++ b/naiveproxy/src/net/log/net_log_event_type_list.h @@ -201,8 +201,8 @@ EVENT_TYPE(HOST_RESOLVER_MANAGER_JOB_REQUEST_DETACH) // } EVENT_TYPE(HOST_RESOLVER_SYSTEM_TASK) -// The creation/completion of a HostResolverManager::DnsTask to manage a -// DnsTransaction. The BEGIN phase contains the following parameters: +// The creation/completion of a HostResolverDnsTask to manage a DnsTransaction. +// The BEGIN phase contains the following parameters: // // { // "secure": , @@ -223,19 +223,27 @@ EVENT_TYPE(HOST_RESOLVER_SYSTEM_TASK) // "saved_results": , // } -EVENT_TYPE(HOST_RESOLVER_MANAGER_DNS_TASK) +EVENT_TYPE(HOST_RESOLVER_DNS_TASK) // Logged when DnsResponseResultExtractor returns an error to -// HostResolverManager::DnsTask when attempting to extract results from a -// DnsResponse. Contains the following parameters: +// HostResolverDnsTask when attempting to extract results from a DnsResponse. +// Contains the following parameters: // // { // "extraction_error": // "dns_query_type": // } -EVENT_TYPE(HOST_RESOLVER_MANAGER_DNS_TASK_EXTRACTION_FAILURE) +EVENT_TYPE(HOST_RESOLVER_DNS_TASK_EXTRACTION_FAILURE) -// Logged when a HostResolverManager::DnsTask times out and cancels unfinished +// Logged when a HostResolverDnsTask extracted HostResolverInternalResults from +// a DnsResponse. Contains the following parameters: +// +// { +// "results": , +// } +EVENT_TYPE(HOST_RESOLVER_DNS_TASK_EXTRACTION_RESULTS) + +// Logged when a HostResolverDnsTask times out and cancels unfinished // transactions. // The event contains the following parameters: // @@ -248,7 +256,7 @@ EVENT_TYPE(HOST_RESOLVER_MANAGER_DNS_TASK_EXTRACTION_FAILURE) // "dns_query_type": , // }], // } -EVENT_TYPE(HOST_RESOLVER_MANAGER_DNS_TASK_TIMEOUT) +EVENT_TYPE(HOST_RESOLVER_DNS_TASK_TIMEOUT) // ------------------------------------------------------------------------ // InitProxyResolver diff --git a/naiveproxy/src/net/log/net_log_source_type_list.h b/naiveproxy/src/net/log/net_log_source_type_list.h index 857078160e..7b11fd88b9 100644 --- a/naiveproxy/src/net/log/net_log_source_type_list.h +++ b/naiveproxy/src/net/log/net_log_source_type_list.h @@ -49,3 +49,4 @@ SOURCE_TYPE(DNS_TRANSACTION) SOURCE_TYPE(NETWORK_CHANGE_NOTIFIER) SOURCE_TYPE(QUIC_SESSION_POOL) SOURCE_TYPE(UDP_CLIENT_SOCKET) +SOURCE_TYPE(QUIC_PROXY_DATAGRAM_CLIENT_SOCKET) diff --git a/naiveproxy/src/net/log/net_log_util.cc b/naiveproxy/src/net/log/net_log_util.cc index a6e8ddb212..89eb356bc7 100644 --- a/naiveproxy/src/net/log/net_log_util.cc +++ b/naiveproxy/src/net/log/net_log_util.cc @@ -419,9 +419,8 @@ NET_EXPORT base::Value::Dict GetNetInfo(URLRequestContext* context) { if (!application_settings.empty()) { base::Value::Dict application_settings_dict; for (const auto& setting : application_settings) { - application_settings_dict.Set( - NextProtoToString(setting.first), - base::HexEncode(setting.second.data(), setting.second.size())); + application_settings_dict.Set(NextProtoToString(setting.first), + base::HexEncode(setting.second)); } status_dict.Set("application_settings", std::move(application_settings_dict)); @@ -504,7 +503,7 @@ NET_EXPORT void CreateNetLogEntriesForActiveObjects( context->AssertCalledOnValidThread(); // Contexts should all be using the same NetLog. DCHECK_EQ((*contexts.begin())->net_log(), context->net_log()); - for (auto* request : *context->url_requests()) { + for (const URLRequest* request : *context->url_requests()) { requests.push_back(request); } } diff --git a/naiveproxy/src/net/log/test_net_log_util.cc b/naiveproxy/src/net/log/test_net_log_util.cc index 258d4d15ff..0a58486be1 100644 --- a/naiveproxy/src/net/log/test_net_log_util.cc +++ b/naiveproxy/src/net/log/test_net_log_util.cc @@ -123,38 +123,37 @@ size_t ExpectLogContainsSomewhereAfter(const std::vector& entries, return i; } -absl::optional GetOptionalStringValueFromParams( +std::optional GetOptionalStringValueFromParams( const NetLogEntry& entry, base::StringPiece path) { if (entry.params.empty()) { - return absl::nullopt; + return std::nullopt; } const std::string* result = entry.params.FindStringByDottedPath(path); if (!result) - return absl::nullopt; + return std::nullopt; return *result; } -absl::optional GetOptionalBooleanValueFromParams(const NetLogEntry& entry, - base::StringPiece path) { +std::optional GetOptionalBooleanValueFromParams(const NetLogEntry& entry, + base::StringPiece path) { if (entry.params.empty()) { - return absl::nullopt; + return std::nullopt; } return entry.params.FindBoolByDottedPath(path); } -absl::optional GetOptionalIntegerValueFromParams(const NetLogEntry& entry, - base::StringPiece path) { +std::optional GetOptionalIntegerValueFromParams(const NetLogEntry& entry, + base::StringPiece path) { if (entry.params.empty()) { - return absl::nullopt; + return std::nullopt; } return entry.params.FindIntByDottedPath(path); } -absl::optional GetOptionalNetErrorCodeFromParams( - const NetLogEntry& entry) { +std::optional GetOptionalNetErrorCodeFromParams(const NetLogEntry& entry) { return GetOptionalIntegerValueFromParams(entry, "net_error"); } diff --git a/naiveproxy/src/net/log/test_net_log_util.h b/naiveproxy/src/net/log/test_net_log_util.h index 2fae1ada3a..77421ff438 100644 --- a/naiveproxy/src/net/log/test_net_log_util.h +++ b/naiveproxy/src/net/log/test_net_log_util.h @@ -6,13 +6,14 @@ #define NET_LOG_TEST_NET_LOG_UTIL_H_ #include + +#include #include #include #include "base/strings/string_piece.h" #include "net/log/net_log_event_type.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -73,14 +74,14 @@ size_t ExpectLogContainsSomewhereAfter(const std::vector& entries, // The following methods return a parameter of the given type at the given path, // or nullopt if there is none. -absl::optional GetOptionalStringValueFromParams( +std::optional GetOptionalStringValueFromParams( const NetLogEntry& entry, base::StringPiece path); -absl::optional GetOptionalBooleanValueFromParams(const NetLogEntry& entry, - base::StringPiece path); -absl::optional GetOptionalIntegerValueFromParams(const NetLogEntry& entry, +std::optional GetOptionalBooleanValueFromParams(const NetLogEntry& entry, base::StringPiece path); -absl::optional GetOptionalNetErrorCodeFromParams(const NetLogEntry& entry); +std::optional GetOptionalIntegerValueFromParams(const NetLogEntry& entry, + base::StringPiece path); +std::optional GetOptionalNetErrorCodeFromParams(const NetLogEntry& entry); // Same as the *Optional* versions above, except will add a Gtest failure if the // value was not present, and then return some default. diff --git a/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc b/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc index 500057b25f..e546c1a5d5 100644 --- a/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc +++ b/naiveproxy/src/net/network_error_logging/network_error_logging_service.cc @@ -5,6 +5,7 @@ #include "net/network_error_logging/network_error_logging_service.h" #include +#include #include #include #include @@ -28,7 +29,6 @@ #include "net/base/url_util.h" #include "net/log/net_log.h" #include "net/reporting/reporting_service.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -307,7 +307,8 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // Policies in the map are unowned; they are pointers to the original in // the PolicyMap. using WildcardPolicyMap = - std::map>; + std::map>>; PolicyMap policies_; WildcardPolicyMap wildcard_policies_; @@ -475,7 +476,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { } bool success = (type == OK) && !IsHttpError(details); - const absl::optional sampling_fraction = + const std::optional sampling_fraction = SampleAndReturnFraction(*policy, success); if (!sampling_fraction.has_value()) return; @@ -488,7 +489,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // A null reporting source token is used since this report is not associated // with any particular document. reporting_service_->QueueReport( - details.uri, absl::nullopt, details.network_anonymization_key, + details.uri, std::nullopt, details.network_anonymization_key, details.user_agent, policy->report_to, kReportType, CreateReportBody(phase_string, type_string, sampling_fraction.value(), details), @@ -526,7 +527,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { RequestOutcome::kDiscardedIPAddressMismatch); return; } - const absl::optional sampling_fraction = + const std::optional sampling_fraction = SampleAndReturnFraction(*policy, details.success); if (!sampling_fraction.has_value()) { RecordSignedExchangeRequestOutcome( @@ -538,7 +539,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { // A null reporting source token is used since this report is not associated // with any particular document. reporting_service_->QueueReport( - details.outer_url, absl::nullopt, details.network_anonymization_key, + details.outer_url, std::nullopt, details.network_anonymization_key, details.user_agent, policy->report_to, kReportType, CreateSignedExchangeReportBody(details, sampling_fraction.value()), 0 /* depth */); @@ -586,7 +587,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { if (json_value.size() > kMaxJsonSize) return false; - absl::optional value = + std::optional value = base::JSONReader::Read(json_value, base::JSON_PARSE_RFC, kMaxJsonDepth); if (!value) return false; @@ -684,8 +685,7 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { if (PoliciesArePersisted() && initialized_) store_->AddNelPolicy(policy); - auto iter_and_result = - policies_.insert(std::make_pair(policy.key, std::move(policy))); + auto iter_and_result = policies_.emplace(policy.key, std::move(policy)); // TODO(crbug.com/1326282): Change this to a DCHECK when we're sure the bug // is fixed. CHECK(iter_and_result.second); @@ -826,20 +826,20 @@ class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService { } // Returns a valid value of matching fraction iff the event should be sampled. - absl::optional SampleAndReturnFraction(const NelPolicy& policy, - bool success) const { + std::optional SampleAndReturnFraction(const NelPolicy& policy, + bool success) const { const double sampling_fraction = success ? policy.success_fraction : policy.failure_fraction; // Sampling fractions are often either 0.0 or 1.0, so in those cases we // can avoid having to call RandDouble(). if (sampling_fraction <= 0.0) - return absl::nullopt; + return std::nullopt; if (sampling_fraction >= 1.0) return sampling_fraction; if (base::RandDouble() >= sampling_fraction) - return absl::nullopt; + return std::nullopt; return sampling_fraction; } diff --git a/naiveproxy/src/net/nqe/effective_connection_type.cc b/naiveproxy/src/net/nqe/effective_connection_type.cc index c3bddc8d07..e62ddb71b4 100644 --- a/naiveproxy/src/net/nqe/effective_connection_type.cc +++ b/naiveproxy/src/net/nqe/effective_connection_type.cc @@ -43,7 +43,7 @@ const char* GetNameForEffectiveConnectionType(EffectiveConnectionType type) { return ""; } -absl::optional GetEffectiveConnectionTypeForName( +std::optional GetEffectiveConnectionTypeForName( base::StringPiece connection_type_name) { if (connection_type_name == kEffectiveConnectionTypeUnknown) return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; @@ -61,7 +61,7 @@ absl::optional GetEffectiveConnectionTypeForName( return EFFECTIVE_CONNECTION_TYPE_3G; if (connection_type_name == kEffectiveConnectionType4G) return EFFECTIVE_CONNECTION_TYPE_4G; - return absl::nullopt; + return std::nullopt; } const char* DeprecatedGetNameForEffectiveConnectionType( diff --git a/naiveproxy/src/net/nqe/effective_connection_type.h b/naiveproxy/src/net/nqe/effective_connection_type.h index c0b0ab8dc6..060a9537ac 100644 --- a/naiveproxy/src/net/nqe/effective_connection_type.h +++ b/naiveproxy/src/net/nqe/effective_connection_type.h @@ -5,9 +5,10 @@ #ifndef NET_NQE_EFFECTIVE_CONNECTION_TYPE_H_ #define NET_NQE_EFFECTIVE_CONNECTION_TYPE_H_ +#include + #include "base/strings/string_piece.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -69,7 +70,7 @@ NET_EXPORT const char* GetNameForEffectiveConnectionType( // |connection_type_name|. If the effective connection type is unavailable or if // |connection_type_name| does not match to a known effective connection type, // an unset value is returned. -NET_EXPORT absl::optional +NET_EXPORT std::optional GetEffectiveConnectionTypeForName(base::StringPiece connection_type_name); // Returns the string equivalent of |type|. Deprecated, and replaced by diff --git a/naiveproxy/src/net/nqe/network_id.h b/naiveproxy/src/net/nqe/network_id.h index 967f9dae32..2878e44d4f 100644 --- a/naiveproxy/src/net/nqe/network_id.h +++ b/naiveproxy/src/net/nqe/network_id.h @@ -58,7 +58,7 @@ struct NET_EXPORT_PRIVATE NetworkID { // range is capped between 0 and 4 to ensure that a change in the value // indicates a non-negligible change in the signal quality. // - // TODO(crbug.com/1495477): This should use absl::optional instead of a magic + // TODO(crbug.com/1495477): This should use std::optional instead of a magic // value. int32_t signal_strength; }; diff --git a/naiveproxy/src/net/nqe/network_qualities_prefs_manager.cc b/naiveproxy/src/net/nqe/network_qualities_prefs_manager.cc index bff22640d4..11f787b307 100644 --- a/naiveproxy/src/net/nqe/network_qualities_prefs_manager.cc +++ b/naiveproxy/src/net/nqe/network_qualities_prefs_manager.cc @@ -4,6 +4,7 @@ #include "net/nqe/network_qualities_prefs_manager.h" +#include #include #include @@ -12,7 +13,6 @@ #include "base/rand_util.h" #include "base/task/sequenced_task_runner.h" #include "net/nqe/network_quality_estimator.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -40,7 +40,7 @@ ParsedPrefs ConvertDictionaryValueToMap(const base::Value::Dict& value) { if (!it.second.is_string()) continue; - absl::optional effective_connection_type = + std::optional effective_connection_type = GetEffectiveConnectionTypeForName(it.second.GetString()); DCHECK(effective_connection_type.has_value()); diff --git a/naiveproxy/src/net/nqe/network_quality_estimator.cc b/naiveproxy/src/net/nqe/network_quality_estimator.cc index 717a1a4920..8d0b8e580b 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator.cc @@ -467,7 +467,7 @@ void NetworkQualityEstimator::OnConnectionTypeChanged( current_network_id_.signal_strength = INT32_MIN; network_quality_ = nqe::internal::NetworkQuality(); - end_to_end_rtt_ = absl::nullopt; + end_to_end_rtt_ = std::nullopt; effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN; rtt_observations_size_at_last_ect_computation_ = 0; throughput_observations_size_at_last_ect_computation_ = 0; @@ -551,7 +551,7 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() { network_quality_.http_rtt()); } - end_to_end_rtt_ = absl::nullopt; + end_to_end_rtt_ = std::nullopt; if (end_to_end_rtt != nqe::internal::InvalidRTT()) { end_to_end_rtt_ = end_to_end_rtt; } @@ -574,9 +574,9 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() { new_throughput_observations_since_last_ect_computation_ = 0; } -absl::optional +std::optional NetworkQualityEstimator::GetOverrideECT() const { - return absl::nullopt; + return std::nullopt; } void NetworkQualityEstimator::ClampKbpsBasedOnEct() { @@ -655,7 +655,7 @@ EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - absl::optional override_ect = GetOverrideECT(); + std::optional override_ect = GetOverrideECT(); if (override_ect) { return override_ect.value(); } @@ -1040,7 +1040,7 @@ void NetworkQualityEstimator::SetTickClockForTesting( void NetworkQualityEstimator::OnUpdatedTransportRTTAvailable( SocketPerformanceWatcherFactory::Protocol protocol, const base::TimeDelta& rtt, - const absl::optional& host) { + const std::optional& host) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_LT(nqe::internal::INVALID_RTT_THROUGHPUT, rtt.InMilliseconds()); Observation observation(rtt.InMilliseconds(), tick_clock_->NowTicks(), @@ -1205,7 +1205,7 @@ void NetworkQualityEstimator:: DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_NE(EFFECTIVE_CONNECTION_TYPE_LAST, effective_connection_type_); - absl::optional override_ect = GetOverrideECT(); + std::optional override_ect = GetOverrideECT(); // TODO(tbansal): Add hysteresis in the notification. for (auto& observer : effective_connection_type_observer_list_) @@ -1236,7 +1236,7 @@ void NetworkQualityEstimator::NotifyEffectiveConnectionTypeObserverIfPresent( if (!effective_connection_type_observer_list_.HasObserver(observer)) return; - absl::optional override_ect = GetOverrideECT(); + std::optional override_ect = GetOverrideECT(); if (override_ect) { observer->OnEffectiveConnectionTypeChanged(override_ect.value()); return; @@ -1317,30 +1317,30 @@ void NetworkQualityEstimator::EnableGetNetworkIdAsynchronously() { } #endif // BUILDFLAG(IS_CHROMEOS_ASH) -absl::optional NetworkQualityEstimator::GetHttpRTT() const { +std::optional NetworkQualityEstimator::GetHttpRTT() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (network_quality_.http_rtt() == nqe::internal::InvalidRTT()) - return absl::optional(); + return std::optional(); return network_quality_.http_rtt(); } -absl::optional NetworkQualityEstimator::GetTransportRTT() +std::optional NetworkQualityEstimator::GetTransportRTT() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (network_quality_.transport_rtt() == nqe::internal::InvalidRTT()) - return absl::optional(); + return std::optional(); return network_quality_.transport_rtt(); } -absl::optional NetworkQualityEstimator::GetDownstreamThroughputKbps() +std::optional NetworkQualityEstimator::GetDownstreamThroughputKbps() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (network_quality_.downstream_throughput_kbps() == nqe::internal::INVALID_RTT_THROUGHPUT) { - return absl::optional(); + return std::optional(); } return network_quality_.downstream_throughput_kbps(); } diff --git a/naiveproxy/src/net/nqe/network_quality_estimator.h b/naiveproxy/src/net/nqe/network_quality_estimator.h index 6268c2e330..9d6d4d2803 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator.h @@ -9,6 +9,7 @@ #include #include +#include #include #include "base/gtest_prod_util.h" @@ -36,7 +37,6 @@ #include "net/nqe/peer_to_peer_connections_count_observer.h" #include "net/nqe/rtt_throughput_estimates_observer.h" #include "net/nqe/socket_watcher_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class TickClock; @@ -144,18 +144,18 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator // time from when the request was sent (this happens after the connection is // established) to the time when the response headers were received. // Virtualized for testing. - virtual absl::optional GetHttpRTT() const; + virtual std::optional GetHttpRTT() const; // Returns the current transport RTT estimate. If the estimate is // unavailable, the returned optional value is null. The RTT at the transport // layer provides an aggregate estimate of the transport RTT as computed by // various underlying TCP and QUIC connections. Virtualized for testing. - virtual absl::optional GetTransportRTT() const; + virtual std::optional GetTransportRTT() const; // Returns the current downstream throughput estimate (in kilobits per // second). If the estimate is unavailable, the returned optional value is // null. - absl::optional GetDownstreamThroughputKbps() const; + std::optional GetDownstreamThroughputKbps() const; // Adds |observer| to the list of RTT and throughput estimate observers. // The observer must register and unregister itself on the same thread. @@ -341,7 +341,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator void OnUpdatedTransportRTTAvailable( SocketPerformanceWatcherFactory::Protocol protocol, const base::TimeDelta& rtt, - const absl::optional& host); + const std::optional& host); // Returns an estimate of network quality at the specified |percentile|. // Only the observations later than |start_time| are taken into account. @@ -393,7 +393,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator // Returns a non-null value if the value of the effective connection type has // been overridden for testing. - virtual absl::optional GetOverrideECT() const; + virtual std::optional GetOverrideECT() const; // Observer list for RTT or throughput estimates. Protected for testing. base::ObserverList::Unchecked @@ -593,7 +593,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator // Current estimate of the network quality. nqe::internal::NetworkQuality network_quality_; - absl::optional end_to_end_rtt_; + std::optional end_to_end_rtt_; // Current effective connection type. It is updated on connection change // events. It is also updated every time there is network traffic (provided @@ -619,7 +619,7 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator // Time when the last RTT observation from a socket watcher was received. base::TimeTicks last_socket_watcher_rtt_notification_; - absl::optional last_signal_strength_check_timestamp_; + std::optional last_signal_strength_check_timestamp_; #if BUILDFLAG(IS_CHROMEOS_ASH) // Whether the network id should be obtained on a worker thread. diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_params.cc b/naiveproxy/src/net/nqe/network_quality_estimator_params.cc index 3ec940c602..5784d83f6c 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_params.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator_params.cc @@ -392,13 +392,13 @@ bool GetForcedEffectiveConnectionTypeOnCellularOnly( kEffectiveConnectionTypeSlow2GOnCellular; } -absl::optional GetInitForcedEffectiveConnectionType( +std::optional GetInitForcedEffectiveConnectionType( const std::map& params) { if (GetForcedEffectiveConnectionTypeOnCellularOnly(params)) { - return absl::nullopt; + return std::nullopt; } std::string forced_value = GetForcedEffectiveConnectionTypeString(params); - absl::optional ect = + std::optional ect = GetEffectiveConnectionTypeForName(forced_value); DCHECK(forced_value.empty() || ect); return ect; @@ -539,7 +539,7 @@ void NetworkQualityEstimatorParams::SetForcedEffectiveConnectionTypeForTesting( forced_effective_connection_type_ = type; } -absl::optional +std::optional NetworkQualityEstimatorParams::GetForcedEffectiveConnectionType( NetworkChangeNotifier::ConnectionType connection_type) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -551,7 +551,7 @@ NetworkQualityEstimatorParams::GetForcedEffectiveConnectionType( net::NetworkChangeNotifier::IsConnectionCellular(connection_type)) { return EFFECTIVE_CONNECTION_TYPE_SLOW_2G; } - return absl::nullopt; + return std::nullopt; } size_t NetworkQualityEstimatorParams::throughput_min_requests_in_flight() diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_params.h b/naiveproxy/src/net/nqe/network_quality_estimator_params.h index 972dfafe95..44fa588d2d 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_params.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator_params.h @@ -6,6 +6,7 @@ #define NET_NQE_NETWORK_QUALITY_ESTIMATOR_PARAMS_H_ #include +#include #include #include "base/sequence_checker.h" @@ -14,7 +15,6 @@ #include "net/base/network_change_notifier.h" #include "net/nqe/effective_connection_type.h" #include "net/nqe/network_quality.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -77,7 +77,7 @@ class NET_EXPORT NetworkQualityEstimatorParams { // the effective connection type that has been forced. Forced ECT can be // forced based on |connection_type| (e.g. Slow-2G on cellular, and default on // other connection type). - absl::optional GetForcedEffectiveConnectionType( + std::optional GetForcedEffectiveConnectionType( NetworkChangeNotifier::ConnectionType connection_type); void SetForcedEffectiveConnectionType( @@ -268,7 +268,7 @@ class NET_EXPORT NetworkQualityEstimatorParams { const int throughput_min_transfer_size_kilobytes_; const double throughput_hanging_requests_cwnd_size_multiplier_; const double weight_multiplier_per_second_; - absl::optional forced_effective_connection_type_; + std::optional forced_effective_connection_type_; const bool forced_effective_connection_type_on_cellular_only_; bool persistent_cache_reading_enabled_; const base::TimeDelta min_socket_watcher_notification_interval_; diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc index 1a62301bf4..649966866f 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc +++ b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.cc @@ -191,7 +191,7 @@ bool TestNetworkQualityEstimator::GetRecentRTT( rtt, observations_count); } -absl::optional TestNetworkQualityEstimator::GetTransportRTT() +std::optional TestNetworkQualityEstimator::GetTransportRTT() const { if (start_time_null_transport_rtt_) return start_time_null_transport_rtt_; @@ -282,7 +282,7 @@ void TestNetworkQualityEstimator:: observer.OnEffectiveConnectionTypeChanged(type); } -absl::optional +std::optional TestNetworkQualityEstimator::GetOverrideECT() const { return effective_connection_type_; } diff --git a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h index 67e0fe9a32..e2b3d8d139 100644 --- a/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h +++ b/naiveproxy/src/net/nqe/network_quality_estimator_test_util.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,6 @@ #include "net/nqe/network_quality_estimator.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -137,7 +137,7 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { recent_transport_rtt_ = recent_transport_rtt; } - absl::optional GetTransportRTT() const override; + std::optional GetTransportRTT() const override; void set_start_time_null_downlink_throughput_kbps( int32_t downlink_throughput_kbps) { @@ -237,15 +237,15 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { // network id and signal strength (instead of invoking platform APIs). nqe::internal::NetworkID GetCurrentNetworkID() const override; - absl::optional GetOverrideECT() const override; + std::optional GetOverrideECT() const override; // Net log observer used to test correctness of NetLog entries. net::RecordingNetLogObserver net_log_observer_; // If set, GetEffectiveConnectionType() and GetRecentEffectiveConnectionType() // would return the set values, respectively. - absl::optional effective_connection_type_; - absl::optional recent_effective_connection_type_; + std::optional effective_connection_type_; + std::optional recent_effective_connection_type_; NetworkChangeNotifier::ConnectionType current_network_type_ = NetworkChangeNotifier::CONNECTION_UNKNOWN; @@ -254,27 +254,27 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { // If set, GetRecentHttpRTT() would return one of the set values. // |start_time_null_http_rtt_| is returned if the |start_time| is null. // Otherwise, |recent_http_rtt_| is returned. - absl::optional start_time_null_http_rtt_; - absl::optional recent_http_rtt_; + std::optional start_time_null_http_rtt_; + std::optional recent_http_rtt_; // If set, GetRecentTransportRTT() would return one of the set values. // |start_time_null_transport_rtt_| is returned if the |start_time| is null. // Otherwise, |recent_transport_rtt_| is returned. - absl::optional start_time_null_transport_rtt_; - absl::optional recent_transport_rtt_; + std::optional start_time_null_transport_rtt_; + std::optional recent_transport_rtt_; // If set, GetRecentDownlinkThroughputKbps() would return one of the set // values. |start_time_null_downlink_throughput_kbps_| is returned if the // |start_time| is null. Otherwise, |recent_downlink_throughput_kbps_| is // returned. - absl::optional start_time_null_downlink_throughput_kbps_; - absl::optional recent_downlink_throughput_kbps_; + std::optional start_time_null_downlink_throughput_kbps_; + std::optional recent_downlink_throughput_kbps_; // If set, GetRTTEstimateInternal() would return the set value. - absl::optional rtt_estimate_internal_; + std::optional rtt_estimate_internal_; // If set, GetRTTEstimateInternal() would return the set value. - absl::optional start_time_null_end_to_end_rtt_; + std::optional start_time_null_end_to_end_rtt_; LocalHttpTestServer embedded_test_server_; @@ -283,7 +283,7 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator { size_t ping_rtt_received_count_ = 0; - absl::optional transport_rtt_observation_count_last_ect_computation_; + std::optional transport_rtt_observation_count_last_ect_computation_; }; } // namespace net diff --git a/naiveproxy/src/net/nqe/network_quality_observation.cc b/naiveproxy/src/net/nqe/network_quality_observation.cc index 0e0f7a539f..4852c66cba 100644 --- a/naiveproxy/src/net/nqe/network_quality_observation.cc +++ b/naiveproxy/src/net/nqe/network_quality_observation.cc @@ -13,13 +13,13 @@ Observation::Observation(int32_t value, base::TimeTicks timestamp, int32_t signal_strength, NetworkQualityObservationSource source) - : Observation(value, timestamp, signal_strength, source, absl::nullopt) {} + : Observation(value, timestamp, signal_strength, source, std::nullopt) {} Observation::Observation(int32_t value, base::TimeTicks timestamp, int32_t signal_strength, NetworkQualityObservationSource source, - const absl::optional& host) + const std::optional& host) : value_(value), timestamp_(timestamp), signal_strength_(signal_strength), diff --git a/naiveproxy/src/net/nqe/network_quality_observation.h b/naiveproxy/src/net/nqe/network_quality_observation.h index e01e284c2e..b08c2ebd98 100644 --- a/naiveproxy/src/net/nqe/network_quality_observation.h +++ b/naiveproxy/src/net/nqe/network_quality_observation.h @@ -7,13 +7,13 @@ #include +#include #include #include "base/time/time.h" #include "net/base/net_export.h" #include "net/nqe/network_quality_estimator_util.h" #include "net/nqe/network_quality_observation_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net::nqe::internal { @@ -32,7 +32,7 @@ class NET_EXPORT_PRIVATE Observation { base::TimeTicks timestamp, int32_t signal_strength, NetworkQualityObservationSource source, - const absl::optional& host); + const std::optional& host); Observation(const Observation& other); Observation& operator=(const Observation& other); @@ -53,7 +53,7 @@ class NET_EXPORT_PRIVATE Observation { NetworkQualityObservationSource source() const { return source_; } // A unique identifier for the remote host which was used for the measurement. - absl::optional host() const { return host_; } + std::optional host() const { return host_; } // Returns the observation categories to which this observation belongs to. std::vector GetObservationCategories() const; @@ -70,7 +70,7 @@ class NET_EXPORT_PRIVATE Observation { NetworkQualityObservationSource source_; - absl::optional host_; + std::optional host_; }; } // namespace net::nqe::internal diff --git a/naiveproxy/src/net/nqe/network_quality_store.cc b/naiveproxy/src/net/nqe/network_quality_store.cc index c274e1e618..0fdda57018 100644 --- a/naiveproxy/src/net/nqe/network_quality_store.cc +++ b/naiveproxy/src/net/nqe/network_quality_store.cc @@ -52,8 +52,7 @@ void NetworkQualityStore::Add( cached_network_qualities_.erase(oldest_entry_iterator); } - cached_network_qualities_.insert( - std::make_pair(network_id, cached_network_quality)); + cached_network_qualities_.emplace(network_id, cached_network_quality); DCHECK_LE(cached_network_qualities_.size(), static_cast(kMaximumNetworkQualityCacheSize)); diff --git a/naiveproxy/src/net/nqe/observation_buffer.cc b/naiveproxy/src/net/nqe/observation_buffer.cc index a79681ec9a..9cbc51ab0f 100644 --- a/naiveproxy/src/net/nqe/observation_buffer.cc +++ b/naiveproxy/src/net/nqe/observation_buffer.cc @@ -65,7 +65,7 @@ void ObservationBuffer::AddObservation(const Observation& observation) { DCHECK_LE(observations_.size(), params_->observation_buffer_size()); } -absl::optional ObservationBuffer::GetPercentile( +std::optional ObservationBuffer::GetPercentile( base::TimeTicks begin_timestamp, int32_t current_signal_strength, int percentile, @@ -88,7 +88,7 @@ absl::optional ObservationBuffer::GetPercentile( } if (weighted_observations.empty()) - return absl::nullopt; + return std::nullopt; double desired_weight = percentile / 100.0 * total_weight; diff --git a/naiveproxy/src/net/nqe/observation_buffer.h b/naiveproxy/src/net/nqe/observation_buffer.h index 4f564176b7..5692c581e5 100644 --- a/naiveproxy/src/net/nqe/observation_buffer.h +++ b/naiveproxy/src/net/nqe/observation_buffer.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -19,7 +20,6 @@ #include "net/nqe/network_quality_estimator_util.h" #include "net/nqe/network_quality_observation.h" #include "net/nqe/network_quality_observation_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { @@ -75,10 +75,10 @@ class NET_EXPORT_PRIVATE ObservationBuffer { // signal strength. |result| must not be null. If |observations_count| is not // null, then it is set to the number of observations that were available // in the observation buffer for computing the percentile. - absl::optional GetPercentile(base::TimeTicks begin_timestamp, - int32_t current_signal_strength, - int percentile, - size_t* observations_count) const; + std::optional GetPercentile(base::TimeTicks begin_timestamp, + int32_t current_signal_strength, + int percentile, + size_t* observations_count) const; void SetTickClockForTesting(const base::TickClock* tick_clock) { tick_clock_ = tick_clock; diff --git a/naiveproxy/src/net/nqe/socket_watcher.cc b/naiveproxy/src/net/nqe/socket_watcher.cc index e0bb766a60..e04248d490 100644 --- a/naiveproxy/src/net/nqe/socket_watcher.cc +++ b/naiveproxy/src/net/nqe/socket_watcher.cc @@ -18,7 +18,7 @@ namespace { // Generate a compact representation for |ip_addr|. For IPv4, all 32 bits // are used and for IPv6, the first 64 bits are used as the remote host // identifier. -absl::optional CalculateIPHash(const IPAddress& ip_addr) { +std::optional CalculateIPHash(const IPAddress& ip_addr) { IPAddressBytes bytes = ip_addr.bytes(); // For IPv4, the first four bytes are taken. For IPv6, the first 8 bytes are diff --git a/naiveproxy/src/net/nqe/socket_watcher.h b/naiveproxy/src/net/nqe/socket_watcher.h index 195502fe28..f862b6dc99 100644 --- a/naiveproxy/src/net/nqe/socket_watcher.h +++ b/naiveproxy/src/net/nqe/socket_watcher.h @@ -5,6 +5,8 @@ #ifndef NET_NQE_SOCKET_WATCHER_H_ #define NET_NQE_SOCKET_WATCHER_H_ +#include + #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" @@ -15,7 +17,6 @@ #include "net/nqe/network_quality_estimator_util.h" #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_performance_watcher_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class SingleThreadTaskRunner; @@ -32,7 +33,7 @@ namespace { typedef base::RepeatingCallback& host)> + const std::optional& host)> OnUpdatedRTTAvailableCallback; typedef base::RepeatingCallback ShouldNotifyRTTCallback; @@ -111,7 +112,7 @@ class NET_EXPORT_PRIVATE SocketWatcher : public SocketPerformanceWatcher { bool first_quic_rtt_notification_received_ = false; // A unique identifier for the remote host that this socket connects to. - const absl::optional host_; + const std::optional host_; }; } // namespace nqe::internal diff --git a/naiveproxy/src/net/nqe/socket_watcher_factory.h b/naiveproxy/src/net/nqe/socket_watcher_factory.h index aad6c50765..cf711c2114 100644 --- a/naiveproxy/src/net/nqe/socket_watcher_factory.h +++ b/naiveproxy/src/net/nqe/socket_watcher_factory.h @@ -6,6 +6,7 @@ #define NET_NQE_SOCKET_WATCHER_FACTORY_H_ #include +#include #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" @@ -17,7 +18,6 @@ #include "net/nqe/network_quality_estimator_util.h" #include "net/socket/socket_performance_watcher.h" #include "net/socket/socket_performance_watcher_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class TickClock; @@ -31,7 +31,7 @@ namespace { typedef base::RepeatingCallback& host)> + const std::optional& host)> OnUpdatedRTTAvailableCallback; typedef base::RepeatingCallback ShouldNotifyRTTCallback; diff --git a/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.cc b/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.cc index 5f1b383606..09f6539996 100644 --- a/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.cc +++ b/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.cc @@ -337,7 +337,7 @@ class ProxyResolverFactoryForProxyChains : public ProxyResolverFactory { // Returns NetLog parameters describing a proxy configuration change. base::Value::Dict NetLogProxyConfigChangedParams( - const absl::optional* old_config, + const std::optional* old_config, const ProxyConfigWithAnnotation* new_config) { base::Value::Dict dict; // The "old_config" is optional -- the first notification will not have @@ -1063,7 +1063,6 @@ ConfiguredProxyResolutionService::~ConfiguredProxyResolutionService() { while (!pending_requests_.empty()) { ConfiguredProxyResolutionRequest* req = *pending_requests_.begin(); req->QueryComplete(ERR_ABORTED); - pending_requests_.erase(req); } } @@ -1089,7 +1088,7 @@ void ConfiguredProxyResolutionService::SetReady() { weak_ptr_factory_.GetWeakPtr(); auto pending_requests_copy = pending_requests_; - for (auto* req : pending_requests_copy) { + for (ConfiguredProxyResolutionRequest* req : pending_requests_copy) { if (!ContainsPendingRequest(req)) continue; @@ -1362,9 +1361,9 @@ ConfiguredProxyResolutionService::ResetProxyConfig(bool reset_fetched_config) { init_proxy_resolver_.reset(); SuspendAllPendingRequests(); resolver_.reset(); - config_ = absl::nullopt; + config_ = std::nullopt; if (reset_fetched_config) - fetched_config_ = absl::nullopt; + fetched_config_ = std::nullopt; current_state_ = STATE_NONE; return previous_state; diff --git a/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.h b/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.h index af361e54b7..a220b49d5f 100644 --- a/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.h +++ b/naiveproxy/src/net/proxy_resolution/configured_proxy_resolution_service.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/proxy_resolution/proxy_resolver.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace base { @@ -154,12 +154,12 @@ class NET_EXPORT ConfiguredProxyResolutionService void OnShutdown() override; // Returns the last configuration fetched from ProxyConfigService. - const absl::optional& fetched_config() const { + const std::optional& fetched_config() const { return fetched_config_; } // Returns the current configuration being used by ProxyConfigService. - const absl::optional& config() const { + const std::optional& config() const { return config_; } @@ -259,7 +259,8 @@ class NET_EXPORT ConfiguredProxyResolutionService class InitProxyResolver; class PacFileDeciderPoller; - typedef std::set PendingRequests; + typedef std::set> + PendingRequests; enum State { STATE_NONE, @@ -362,8 +363,8 @@ class NET_EXPORT ConfiguredProxyResolutionService // and custom PAC url). // // These are "optional" as their value remains unset while being calculated. - absl::optional fetched_config_; - absl::optional config_; + std::optional fetched_config_; + std::optional config_; // Map of the known bad proxies and the information about the retry time. ProxyRetryInfoMap proxy_retry_info_; diff --git a/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.cc index a66ab7c657..7c694fddd6 100644 --- a/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.cc +++ b/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.cc @@ -585,7 +585,7 @@ MultiThreadedProxyResolverFactory::MultiThreadedProxyResolverFactory( } MultiThreadedProxyResolverFactory::~MultiThreadedProxyResolverFactory() { - for (auto* job : jobs_) { + for (Job* job : jobs_) { job->FactoryDestroyed(); } } diff --git a/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.h b/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.h index a659f0f307..447899656c 100644 --- a/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.h +++ b/naiveproxy/src/net/proxy_resolution/multi_threaded_proxy_resolver.h @@ -10,6 +10,7 @@ #include #include +#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" @@ -73,7 +74,7 @@ class NET_EXPORT_PRIVATE MultiThreadedProxyResolverFactory const size_t max_num_threads_; - std::set jobs_; + std::set> jobs_; }; } // namespace net diff --git a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc index 63c24374f2..205d1a9e3b 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_config_service_android.cc @@ -222,8 +222,7 @@ std::string ParseOverrideRules( return "Invalid Proxy URL: " + rule.proxy_url; } else if (proxy_chain.is_multi_proxy()) { return "Unsupported multi proxy chain: " + rule.proxy_url; - } else if (proxy_chain.is_single_proxy() && - proxy_chain.GetProxyServer(/*chain_index=*/0).is_quic()) { + } else if (proxy_chain.is_single_proxy() && proxy_chain.First().is_quic()) { return "Unsupported proxy scheme: " + rule.proxy_url; } diff --git a/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.cc b/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.cc index ed483ef6e1..1256fe4d90 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.cc @@ -106,7 +106,7 @@ std::string FixupProxyHostScheme(ProxyServer::Scheme scheme, } ProxyConfigWithAnnotation GetConfigOrDirect( - const absl::optional& optional_config) { + const std::optional& optional_config) { if (optional_config) return optional_config.value(); @@ -148,7 +148,7 @@ bool ProxyConfigServiceLinux::Delegate::GetProxyFromEnvVar( result_chain); } -absl::optional +std::optional ProxyConfigServiceLinux::Delegate::GetConfigFromEnv() { ProxyConfig config; @@ -219,7 +219,7 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromEnv() { return !no_proxy.empty() ? ProxyConfigWithAnnotation( config, NetworkTrafficAnnotationTag(traffic_annotation_)) - : absl::optional(); + : std::optional(); } // Note that this uses "suffix" matching. So a bypass of "google.com" // is understood to mean a bypass of "*google.com". @@ -1070,7 +1070,7 @@ bool ProxyConfigServiceLinux::Delegate::GetProxyFromSettings( return false; } -absl::optional +std::optional ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { ProxyConfig config; config.set_from_system(true); @@ -1079,7 +1079,7 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { if (!setting_getter_->GetString(SettingGetter::PROXY_MODE, &mode)) { // We expect this to always be set, so if we don't see it then we probably // have a gsettings problem, and so we don't have a valid proxy config. - return absl::nullopt; + return std::nullopt; } if (mode == "none") { // Specifically specifies no proxy. @@ -1098,7 +1098,7 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { pac_url_str = "file://" + pac_url_str; GURL pac_url(pac_url_str); if (!pac_url.is_valid()) - return absl::nullopt; + return std::nullopt; config.set_pac_url(pac_url); return ProxyConfigWithAnnotation( config, NetworkTrafficAnnotationTag(traffic_annotation_)); @@ -1111,7 +1111,7 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { if (mode != "manual") { // Mode is unrecognized. - return absl::nullopt; + return std::nullopt; } bool use_http_proxy; if (setting_getter_->GetBool(SettingGetter::PROXY_USE_HTTP_PROXY, @@ -1175,7 +1175,7 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { if (config.proxy_rules().empty()) { // Manual mode but we couldn't parse any rules. - return absl::nullopt; + return std::nullopt; } // Check for authentication, just so we can warn. @@ -1216,8 +1216,8 @@ ProxyConfigServiceLinux::Delegate::GetConfigFromSettings() { ProxyConfigServiceLinux::Delegate::Delegate( std::unique_ptr env_var_getter, - absl::optional> setting_getter, - absl::optional traffic_annotation) + std::optional> setting_getter, + std::optional traffic_annotation) : env_var_getter_(std::move(env_var_getter)) { if (traffic_annotation) { traffic_annotation_ = @@ -1291,7 +1291,7 @@ void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( // does so even if the proxy mode is set to auto, which would // mislead us. - cached_config_ = absl::nullopt; + cached_config_ = std::nullopt; if (setting_getter_ && setting_getter_->Init(glib_task_runner)) { cached_config_ = GetConfigFromSettings(); } @@ -1387,8 +1387,7 @@ void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { scoped_refptr required_loop = setting_getter_->GetNotificationTaskRunner(); DCHECK(!required_loop.get() || required_loop->RunsTasksInCurrentSequence()); - absl::optional new_config = - GetConfigFromSettings(); + std::optional new_config = GetConfigFromSettings(); // See if it is different from what we had before. if (new_config.has_value() != reference_config_.has_value() || @@ -1408,7 +1407,7 @@ void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { } void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( - const absl::optional& new_config) { + const std::optional& new_config) { DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); VLOG(1) << "Proxy configuration changed"; cached_config_ = new_config; @@ -1445,8 +1444,8 @@ void ProxyConfigServiceLinux::Delegate::OnDestroy() { ProxyConfigServiceLinux::ProxyConfigServiceLinux() : delegate_(base::MakeRefCounted(base::Environment::Create(), - absl::nullopt, - absl::nullopt)) {} + std::nullopt, + std::nullopt)) {} ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { delegate_->PostDestroyTask(); @@ -1456,7 +1455,7 @@ ProxyConfigServiceLinux::ProxyConfigServiceLinux( std::unique_ptr env_var_getter, const NetworkTrafficAnnotationTag& traffic_annotation) : delegate_(base::MakeRefCounted(std::move(env_var_getter), - absl::nullopt, + std::nullopt, traffic_annotation)) {} ProxyConfigServiceLinux::ProxyConfigServiceLinux( diff --git a/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.h b/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.h index 63a386bd45..0c0c998b5a 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.h +++ b/naiveproxy/src/net/proxy_resolution/proxy_config_service_linux.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -20,7 +21,6 @@ #include "net/base/proxy_server.h" #include "net/proxy_resolution/proxy_config_service.h" #include "net/proxy_resolution/proxy_config_with_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class SingleThreadTaskRunner; @@ -173,8 +173,8 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceLinux : public ProxyConfigService { // Test code can set |setting_getter| and |traffic_annotation|. If left // unspecified, reasonable defaults will be used. Delegate(std::unique_ptr env_var_getter, - absl::optional> setting_getter, - absl::optional traffic_annotation); + std::optional> setting_getter, + std::optional traffic_annotation); Delegate(const Delegate&) = delete; Delegate& operator=(const Delegate&) = delete; @@ -228,7 +228,7 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceLinux : public ProxyConfigService { ProxyChain* result_chain); // Returns a proxy config based on the environment variables, or empty value // on failure. - absl::optional GetConfigFromEnv(); + std::optional GetConfigFromEnv(); // Obtains host and port config settings and parses a proxy server // specification from it and puts it in result. Returns true if the @@ -237,12 +237,12 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceLinux : public ProxyConfigService { ProxyServer* result_server); // Returns a proxy config based on the settings, or empty value // on failure. - absl::optional GetConfigFromSettings(); + std::optional GetConfigFromSettings(); // This method is posted from the glib thread to the main TaskRunner to // carry the new config information. void SetNewProxyConfig( - const absl::optional& new_config); + const std::optional& new_config); // This method is run on the getter's notification thread. void SetUpNotifications(); @@ -253,12 +253,12 @@ class NET_EXPORT_PRIVATE ProxyConfigServiceLinux : public ProxyConfigService { // Cached proxy configuration, to be returned by // GetLatestProxyConfig. Initially populated from the glib thread, but // afterwards only accessed from the main TaskRunner. - absl::optional cached_config_; + std::optional cached_config_; // A copy kept on the glib thread of the last seen proxy config, so as // to avoid posting a call to SetNewProxyConfig when we get a // notification but the config has not actually changed. - absl::optional reference_config_; + std::optional reference_config_; // The task runner for the glib thread, aka main browser thread. This thread // is where we run the glib main loop (see diff --git a/naiveproxy/src/net/proxy_resolution/proxy_info.cc b/naiveproxy/src/net/proxy_resolution/proxy_info.cc index 50691b546e..e5b6546f73 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_info.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_info.cc @@ -68,72 +68,6 @@ std::string ProxyInfo::ToPacString() const { return proxy_list_.ToPacString(); } -bool ProxyInfo::is_https() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return true; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_https(); -} - -bool ProxyInfo::is_http_like() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return true; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_http_like(); -} - -bool ProxyInfo::is_secure_http_like() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return true; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_secure_http_like(); -} - -bool ProxyInfo::is_http() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return false; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_http(); -} - -bool ProxyInfo::is_quic() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return false; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_quic(); -} - -bool ProxyInfo::is_socks() const { - if (is_empty() || is_direct()) { - return false; - } - if (proxy_chain().is_multi_proxy()) { - CHECK(AllChainProxiesAreHttps()); - return false; - } - return proxy_chain().GetProxyServer(/*chain_index=*/0).is_socks(); -} - bool ProxyInfo::is_for_ip_protection() const { if (is_empty()) { return false; diff --git a/naiveproxy/src/net/proxy_resolution/proxy_info.h b/naiveproxy/src/net/proxy_resolution/proxy_info.h index 7b969d0de6..fb586f77cf 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_info.h +++ b/naiveproxy/src/net/proxy_resolution/proxy_info.h @@ -77,46 +77,21 @@ class NET_EXPORT ProxyInfo { return is_direct() && proxy_list_.size() == 1 && proxy_retry_info_.empty(); } + // Return true if there is at least one proxy chain, and at least one proxy + // server in that chain matches the given predicate. + template + bool AnyProxyInChain(Predicate p) const { + if (is_empty()) { + return false; + } + const std::vector& proxy_servers = + proxy_chain().proxy_servers(); + return std::any_of(proxy_servers.begin(), proxy_servers.end(), p); + } + // Returns true if any of the contained ProxyChains are multi-proxy. bool ContainsMultiProxyChain() const; - // Returns true if the first valid proxy server is an https proxy. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_https() const; - - // Returns true if the first proxy server is an HTTP compatible proxy. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_http_like() const; - - // Returns true if the first proxy server is an HTTP compatible proxy over a - // secure connection. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_secure_http_like() const; - - // Returns true if the first valid proxy server is an http proxy. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_http() const; - - // Returns true if the first valid proxy server is a quic proxy. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_quic() const; - - // Returns true if the first valid proxy server is a socks server. - // TODO(https://crbug.com/1491092): Remove this method in favor of checking - // the corresponding property of the relevant proxy server from the next - // proxy chain in the proxy list. - bool is_socks() const; - // Returns true if this proxy info has no proxies left to try. bool is_empty() const { return proxy_list_.IsEmpty(); diff --git a/naiveproxy/src/net/proxy_resolution/proxy_list.cc b/naiveproxy/src/net/proxy_resolution/proxy_list.cc index 9032f75ac6..5f8466c0b1 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_list.cc +++ b/naiveproxy/src/net/proxy_resolution/proxy_list.cc @@ -163,8 +163,7 @@ std::string ProxyList::ToPacString() const { CHECK(!proxy_chain.is_multi_proxy()); proxy_list += proxy_chain.is_direct() ? "DIRECT" - : ProxyServerToPacResultElement( - proxy_chain.GetProxyServer(/*chain_index=*/0)); + : ProxyServerToPacResultElement(proxy_chain.First()); } return proxy_list.empty() ? std::string() : proxy_list; } @@ -181,8 +180,7 @@ std::string ProxyList::ToDebugString() const { } else { proxy_list += proxy_chain.is_direct() ? "DIRECT" - : ProxyServerToPacResultElement( - proxy_chain.GetProxyServer(/*chain_index=*/0)); + : ProxyServerToPacResultElement(proxy_chain.First()); } } return proxy_list; diff --git a/naiveproxy/src/net/proxy_resolution/proxy_list.h b/naiveproxy/src/net/proxy_resolution/proxy_list.h index b68f33b7a4..d7db976cbf 100644 --- a/naiveproxy/src/net/proxy_resolution/proxy_list.h +++ b/naiveproxy/src/net/proxy_resolution/proxy_list.h @@ -8,13 +8,13 @@ #include #include +#include #include #include #include "net/base/net_export.h" #include "net/base/proxy_server.h" #include "net/proxy_resolution/proxy_retry_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class TimeDelta; diff --git a/naiveproxy/src/net/proxy_resolution/win/windows_system_proxy_resolution_service.h b/naiveproxy/src/net/proxy_resolution/win/windows_system_proxy_resolution_service.h index e24b2279ab..d60e30818b 100644 --- a/naiveproxy/src/net/proxy_resolution/win/windows_system_proxy_resolution_service.h +++ b/naiveproxy/src/net/proxy_resolution/win/windows_system_proxy_resolution_service.h @@ -74,7 +74,9 @@ class NET_EXPORT WindowsSystemProxyResolutionService std::unique_ptr windows_system_proxy_resolver, NetLog* net_log); - typedef std::set PendingRequests; + typedef std::set< + raw_ptr> + PendingRequests; [[nodiscard]] bool ContainsPendingRequest( WindowsSystemProxyResolutionRequest* req); diff --git a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc index 42526eba87..b4cc447f1e 100644 --- a/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc +++ b/naiveproxy/src/net/quic/bidirectional_stream_quic_impl.cc @@ -116,7 +116,7 @@ int BidirectionalStreamQuicImpl::WriteHeaders() { http_request_info.method = request_info_->method; http_request_info.extra_headers = request_info_->extra_headers; - CreateSpdyHeadersFromHttpRequest(http_request_info, absl::nullopt, + CreateSpdyHeadersFromHttpRequest(http_request_info, std::nullopt, http_request_info.extra_headers, &headers); int rv = stream_->WriteHeaders(std::move(headers), request_info_->end_stream_on_headers, nullptr); diff --git a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc index 5c45ee1a1c..cb9a29b76f 100644 --- a/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc +++ b/naiveproxy/src/net/quic/crypto/proof_source_chromium.cc @@ -122,8 +122,7 @@ bool ProofSourceChromium::GetProofInner( proof->signature.assign(reinterpret_cast(signature.data()), signature.size()); *out_chain = chain_; - VLOG(1) << "signature: " - << base::HexEncode(proof->signature.data(), proof->signature.size()); + VLOG(1) << "signature: " << base::HexEncode(proof->signature); proof->leaf_cert_scts = signed_certificate_timestamp_; return true; } diff --git a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc index ff7e5a8b7c..96e7abee31 100644 --- a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc +++ b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.cc @@ -119,7 +119,7 @@ void RecordNetLogQuicSessionClientStateChanged( NetLogWithSource& net_log, WebTransportState last_state, WebTransportState next_state, - const absl::optional& error) { + const std::optional& error) { net_log.AddEvent( NetLogEventType::QUIC_SESSION_WEBTRANSPORT_CLIENT_STATE_CHANGED, [&] { auto dict = base::Value::Dict() @@ -239,11 +239,10 @@ class DedicatedWebTransportHttp3ClientSession return stream_ptr; } - void OnDatagramProcessed( - absl::optional status) override { + void OnDatagramProcessed(std::optional status) override { client_->OnDatagramProcessed( - status.has_value() ? absl::optional(*status) - : absl::optional()); + status.has_value() ? std::optional(*status) + : std::optional()); } private: @@ -414,7 +413,7 @@ void DedicatedWebTransportHttp3Client::Connect() { } void DedicatedWebTransportHttp3Client::Close( - const absl::optional& close_info) { + const std::optional& close_info) { CHECK(session()); base::TimeDelta probe_timeout = base::Microseconds( connection_->sent_packet_manager().GetPtoDelay().ToMicroseconds()); @@ -549,7 +548,7 @@ int DedicatedWebTransportHttp3Client::DoResolveHost() { next_connect_state_ = CONNECT_STATE_RESOLVE_HOST_COMPLETE; HostResolver::ResolveHostParameters parameters; resolve_host_request_ = context_->host_resolver()->CreateRequest( - url::SchemeHostPort(url_), anonymization_key_, net_log_, absl::nullopt); + url::SchemeHostPort(url_), anonymization_key_, net_log_, std::nullopt); return resolve_host_request_->Start(base::BindOnce( &DedicatedWebTransportHttp3Client::DoLoop, base::Unretained(this))); } @@ -972,7 +971,7 @@ void DedicatedWebTransportHttp3Client::OnConnectionClosed( } void DedicatedWebTransportHttp3Client::OnDatagramProcessed( - absl::optional status) { + std::optional status) { visitor_->OnDatagramProcessed(status); } diff --git a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h index 44605eb319..d3674db910 100644 --- a/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h +++ b/naiveproxy/src/net/quic/dedicated_web_transport_http3_client.h @@ -5,6 +5,8 @@ #ifndef NET_QUIC_DEDICATED_WEB_TRANSPORT_HTTP3_CLIENT_H_ #define NET_QUIC_DEDICATED_WEB_TRANSPORT_HTTP3_CLIENT_H_ +#include + #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/task/sequenced_task_runner.h" @@ -27,7 +29,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/quic/core/web_transport_interface.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -59,7 +60,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client // Connect() is an asynchronous operation. Once the operation is finished, // OnConnected() or OnConnectionFailed() is called on the Visitor. void Connect() override; - void Close(const absl::optional& close_info) override; + void Close(const std::optional& close_info) override; quic::WebTransportSession* session() override; @@ -69,7 +70,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client void OnConnectStreamAborted(); void OnConnectStreamDeleted(); void OnCloseTimeout(); - void OnDatagramProcessed(absl::optional status); + void OnDatagramProcessed(std::optional status); // QuicTransportClientSession::ClientVisitor methods. void OnSessionReady() override; @@ -165,7 +166,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client WebTransportState state_ = WebTransportState::NEW; ConnectState next_connect_state_ = CONNECT_STATE_NONE; - absl::optional error_; + std::optional error_; bool retried_with_new_version_ = false; bool session_ready_ = false; bool safe_to_report_error_details_ = false; @@ -184,7 +185,7 @@ class NET_EXPORT DedicatedWebTransportHttp3Client quic::DeterministicConnectionIdGenerator connection_id_generator_{ quic::kQuicDefaultConnectionIdLength}; - absl::optional close_info_; + std::optional close_info_; base::OneShotTimer close_timeout_timer_; base::WeakPtrFactory weak_factory_{this}; diff --git a/naiveproxy/src/net/quic/mock_quic_data.cc b/naiveproxy/src/net/quic/mock_quic_data.cc index dd29929022..532324a76a 100644 --- a/naiveproxy/src/net/quic/mock_quic_data.cc +++ b/naiveproxy/src/net/quic/mock_quic_data.cc @@ -16,16 +16,33 @@ void MockQuicData::AddConnect(IoMode mode, int rv) { connect_ = std::make_unique(mode, rv); } +void MockQuicData::AddRead(IoMode mode, + std::unique_ptr packet) { + reads_.emplace_back(mode, packet->data(), packet->length(), + sequence_number_++, + static_cast(packet->ecn_codepoint())); + packets_.push_back(std::move(packet)); +} void MockQuicData::AddRead(IoMode mode, std::unique_ptr packet) { reads_.emplace_back(mode, packet->data(), packet->length(), - sequence_number_++); + sequence_number_++, /*tos=*/0); packets_.push_back(std::move(packet)); } void MockQuicData::AddRead(IoMode mode, int rv) { reads_.emplace_back(mode, rv, sequence_number_++); } +void MockQuicData::AddReadPause() { + // Add a sentinel value that indicates a read pause. + AddRead(ASYNC, ERR_IO_PENDING); +} + +void MockQuicData::AddReadPauseForever() { + // Add a sentinel value that indicates a read pause forever. + AddRead(SYNCHRONOUS, ERR_IO_PENDING); +} + void MockQuicData::AddWrite(IoMode mode, std::unique_ptr packet) { writes_.emplace_back(mode, packet->data(), packet->length(), @@ -44,6 +61,11 @@ void MockQuicData::AddWrite(IoMode mode, packets_.push_back(std::move(packet)); } +void MockQuicData::AddWritePause() { + // Add a sentinel value that indicates a write pause. + AddWrite(ASYNC, ERR_IO_PENDING); +} + void MockQuicData::AddSocketDataToFactory(MockClientSocketFactory* factory) { factory->AddSocketDataProvider(InitializeAndGetSequencedSocketData()); } diff --git a/naiveproxy/src/net/quic/mock_quic_data.h b/naiveproxy/src/net/quic/mock_quic_data.h index 9c9dea776f..f0283d4094 100644 --- a/naiveproxy/src/net/quic/mock_quic_data.h +++ b/naiveproxy/src/net/quic/mock_quic_data.h @@ -13,6 +13,15 @@ namespace net::test { // Helper class to encapsulate MockReads and MockWrites for QUIC. // Simplify ownership issues and the interaction with the MockSocketFactory. +// +// To use, construct an instance, call the `Add*` methods in the desired order, +// and then call `AddSocketDataToFactory(socket_factory)` to add a socket with +// the defined behavior to the socket factory. Alternately, use +// `InitializeAndGetSequencedSocketData()` and pass the result to a mock socket +// like `MockUDPClientSocket`. +// +// The MockQuicData instance must remain live until the socket is created and +// ultimately closed. class MockQuicData { public: explicit MockQuicData(quic::ParsedQuicVersion version); @@ -23,13 +32,22 @@ class MockQuicData { void AddConnect(IoMode mode, int rv); // Adds a read at the next sequence number which will read |packet| - // synchronously or asynchronously based on |mode|. + // synchronously or asynchronously based on |mode|. The QuicReceivedPacket + // version includes an ECN codepoint. + void AddRead(IoMode mode, std::unique_ptr packet); void AddRead(IoMode mode, std::unique_ptr packet); // Adds a read at the next sequence number which will return |rv| either // synchronously or asynchronously based on |mode|. void AddRead(IoMode mode, int rv); + // Adds a pause, meaning that reads will return ERR_IO_PENDING until + // `Resume()` is called. Read and write cannot both be paused simultaneously. + void AddReadPause(); + + // Like `AddReadPause`, but cannot be resumed. + void AddReadPauseForever(); + // Adds a write at the next sequence number which will write |packet| // synchronously or asynchronously based on |mode|. void AddWrite(IoMode mode, std::unique_ptr packet); @@ -44,6 +62,10 @@ class MockQuicData { int rv, std::unique_ptr packet); + // Adds a pause, meaning that writes will return ERR_IO_PENDING until + // `Resume()` is called. Read and write cannot both be paused simultaneously. + void AddWritePause(); + // Adds the reads and writes to |factory|. void AddSocketDataToFactory(MockClientSocketFactory* factory); @@ -56,10 +78,13 @@ class MockQuicData { // Resumes I/O after it is paused. void Resume(); - // Creates a new SequencedSocketData owned by this instance of MockQuicData. - // Returns a pointer to the newly created SequencedSocketData. + // Creates a new `SequencedSocketData` owned by this instance of + // `MockQuicData`. Returns a pointer to the newly created + // `SequencedSocketData`. SequencedSocketData* InitializeAndGetSequencedSocketData(); + // Get the `SequencedSocketData` created by `AddSocketDataToFactory` or + // `InitializeAndGetSequencedSocketData`. SequencedSocketData* GetSequencedSocketData(); private: diff --git a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc index 968b82f83b..b3dec9a6c0 100644 --- a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc +++ b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.cc @@ -15,18 +15,18 @@ QuicFlagSaverImpl::QuicFlagSaverImpl() { #define QUIC_FLAG(flag, value) saved_##flag##_ = FLAGS_##flag; #include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; -#include "net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; +#include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG } QuicFlagSaverImpl::~QuicFlagSaverImpl() { #define QUIC_FLAG(flag, value) FLAGS_##flag = saved_##flag##_; #include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; -#include "net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; +#include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG } QuicFlagChecker::QuicFlagChecker() { @@ -38,28 +38,28 @@ QuicFlagChecker::QuicFlagChecker() { #include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG_CHECK(type, flag, value) \ +#define QUICHE_PROTOCOL_FLAG_CHECK(type, flag, value) \ CHECK_EQ((type)value, FLAGS_##flag) \ << "Flag set to an unexpected value. A prior test is likely " \ << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \ "avoid this issue."; -#define DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \ - QUIC_PROTOCOL_FLAG_CHECK(type, flag, value); +#define DEFINE_QUICHE_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \ + QUICHE_PROTOCOL_FLAG_CHECK(type, flag, value); -#define DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES(type, flag, internal_value, \ - external_value, doc) \ - QUIC_PROTOCOL_FLAG_CHECK(type, flag, external_value); +#define DEFINE_QUICHE_PROTOCOL_FLAG_TWO_VALUES(type, flag, internal_value, \ + external_value, doc) \ + QUICHE_PROTOCOL_FLAG_CHECK(type, flag, external_value); #define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6 -#define QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(...) \ - GET_6TH_ARG(__VA_ARGS__, DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES, \ - DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE) -#define QUIC_PROTOCOL_FLAG(...) \ - QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) -#include "net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG -#undef QUIC_PROTOCOL_FLAG_MACRO_CHOOSER +#define QUICHE_PROTOCOL_FLAG_MACRO_CHOOSER(...) \ + GET_6TH_ARG(__VA_ARGS__, DEFINE_QUICHE_PROTOCOL_FLAG_TWO_VALUES, \ + DEFINE_QUICHE_PROTOCOL_FLAG_SINGLE_VALUE) +#define QUICHE_PROTOCOL_FLAG(...) \ + QUICHE_PROTOCOL_FLAG_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) +#include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG +#undef QUICHE_PROTOCOL_FLAG_MACRO_CHOOSER #undef GET_6TH_ARG -#undef DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES -#undef DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE -#undef QUIC_PROTOCOL_FLAG_CHECK +#undef DEFINE_QUICHE_PROTOCOL_FLAG_TWO_VALUES +#undef DEFINE_QUICHE_PROTOCOL_FLAG_SINGLE_VALUE +#undef QUICHE_PROTOCOL_FLAG_CHECK } diff --git a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h index aab944e256..55e403f4bc 100644 --- a/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h +++ b/naiveproxy/src/net/quic/platform/impl/quic_test_flags_utils.h @@ -16,9 +16,9 @@ class QuicFlagSaverImpl { #define QUIC_FLAG(flag, value) bool saved_##flag##_; #include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; -#include "net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; +#include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG }; //// Checks if all QUIC flags are on their default values on construction. diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.cc b/naiveproxy/src/net/quic/quic_chromium_client_session.cc index a07f7f2be4..ddd38c9970 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.cc @@ -1131,8 +1131,8 @@ void QuicChromiumClientSession::OnAcceptChFrameReceivedViaAlps( continue; } has_valid_entry = true; - accept_ch_entries_received_via_alps_.insert( - std::make_pair(std::move(scheme_host_port), entry.value)); + accept_ch_entries_received_via_alps_.emplace(std::move(scheme_host_port), + entry.value); net_log_.AddEvent(NetLogEventType::QUIC_ACCEPT_CH_FRAME_RECEIVED, [&] { return NetLogAcceptChFrameReceivedParams(entry); }); @@ -1393,7 +1393,7 @@ int QuicChromiumClientSession::GetNumSentClientHellos() const { } bool QuicChromiumClientSession::CanPool( - const std::string& hostname, + std::string_view hostname, const QuicSessionKey& other_session_key) const { DCHECK(connection()->connected()); if (!session_key_.CanUseForAliasing(other_session_key)) { @@ -1737,6 +1737,10 @@ void QuicChromiumClientSession::OnConnectionClosed( } if (const quic::QuicConnection::MultiPortStats* multi_port_stats = connection()->multi_port_stats()) { + UMA_HISTOGRAM_COUNTS_1000("Net.QuicMultiPort.NumProbeAttempts", + multi_port_stats->num_client_probing_attempts); + UMA_HISTOGRAM_COUNTS_1000("Net.QuicMultiPort.NumSuccessfulProbes", + multi_port_stats->num_successful_probes); UMA_HISTOGRAM_COUNTS_1000( "Net.QuicMultiPort.NumMultiPortFailureWhenPathNotDegrading", multi_port_stats diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session.h b/naiveproxy/src/net/quic/quic_chromium_client_session.h index 17f33bb268..692802e5eb 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session.h +++ b/naiveproxy/src/net/quic/quic_chromium_client_session.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "base/containers/flat_map.h" @@ -775,7 +776,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession // (its own hostname and port fields are ignored). If this is a secure QUIC // session, then |hostname| must match the certificate presented during the // handshake. - bool CanPool(const std::string& hostname, + bool CanPool(std::string_view hostname, const QuicSessionKey& other_session_key) const; const quic::QuicServerId& server_id() const { @@ -895,7 +896,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession private: friend class test::QuicChromiumClientSessionPeer; - typedef std::set HandleSet; + typedef std::set> HandleSet; typedef std::list StreamRequestQueue; bool WasConnectionEverUsed(); diff --git a/naiveproxy/src/net/quic/quic_chromium_client_session_peer.cc b/naiveproxy/src/net/quic/quic_chromium_client_session_peer.cc index 9c99743bf6..6b3f2a3873 100644 --- a/naiveproxy/src/net/quic/quic_chromium_client_session_peer.cc +++ b/naiveproxy/src/net/quic/quic_chromium_client_session_peer.cc @@ -4,9 +4,17 @@ #include "net/quic/quic_chromium_client_session_peer.h" -#include "net/dns/public/secure_dns_policy.h" -#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include +#include "net/base/network_anonymization_key.h" +#include "net/base/privacy_mode.h" +#include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" +#include "net/dns/public/secure_dns_policy.h" +#include "net/quic/quic_session_key.h" +#include "net/socket/socket_tag.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" namespace net::test { // static void QuicChromiumClientSessionPeer::SetHostname( @@ -15,9 +23,12 @@ void QuicChromiumClientSessionPeer::SetHostname( quic::QuicServerId server_id(hostname, session->session_key_.server_id().port(), session->session_key_.privacy_mode()); - session->session_key_ = - QuicSessionKey(server_id, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, /*require_dns_https_alpn=*/false); + session->session_key_ = QuicSessionKey( + server_id, session->session_key_.proxy_chain(), + session->session_key_.session_usage(), session->session_key_.socket_tag(), + session->session_key_.network_anonymization_key(), + session->session_key_.secure_dns_policy(), + session->session_key_.require_dns_https_alpn()); } // static diff --git a/naiveproxy/src/net/quic/quic_chromium_packet_reader.cc b/naiveproxy/src/net/quic/quic_chromium_packet_reader.cc index a1530f64ae..a9366992d8 100644 --- a/naiveproxy/src/net/quic/quic_chromium_packet_reader.cc +++ b/naiveproxy/src/net/quic/quic_chromium_packet_reader.cc @@ -8,9 +8,11 @@ #include "base/location.h" #include "base/metrics/histogram_macros.h" #include "base/task/single_thread_task_runner.h" +#include "net/base/features.h" #include "net/base/net_errors.h" #include "net/quic/address_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" namespace net { @@ -35,7 +37,8 @@ QuicChromiumPacketReader::QuicChromiumPacketReader( yield_after_duration_(yield_after_duration), yield_after_(quic::QuicTime::Infinite()), read_buffer_(base::MakeRefCounted(kReadBufferSize)), - net_log_(net_log) {} + net_log_(net_log), + report_ecn_(base::FeatureList::IsEnabled(net::features::kReceiveEcn)) {} QuicChromiumPacketReader::~QuicChromiumPacketReader() = default; @@ -80,6 +83,11 @@ void QuicChromiumPacketReader::CloseSocket() { socket_->Close(); } +static_assert(static_cast(quic::ECN_NOT_ECT) == ECN_NOT_ECT && + static_cast(quic::ECN_ECT1) == ECN_ECT1 && + static_cast(quic::ECN_ECT0) == ECN_ECT0 && + static_cast(quic::ECN_CE) == ECN_CE, + "Mismatch ECN codepoint values"); bool QuicChromiumPacketReader::ProcessReadResult(int result) { read_pending_ = false; if (result <= 0 && net_log_.IsCapturing()) { @@ -100,7 +108,17 @@ bool QuicChromiumPacketReader::ProcessReadResult(int result) { return visitor_->OnReadError(result, socket_.get()); } - quic::QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now()); + quic::QuicEcnCodepoint ecn = quic::ECN_NOT_ECT; + if (report_ecn_) { + DscpAndEcn tos = socket_->GetLastTos(); + ecn = static_cast(tos.ecn); + } + quic::QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now(), + /*owns_buffer=*/false, /*ttl=*/0, + /*ttl_valid=*/true, + /*packet_headers=*/nullptr, + /*headers_length=*/0, + /*owns_header_buffer=*/false, ecn); IPEndPoint local_address; IPEndPoint peer_address; socket_->GetLocalAddress(&local_address); @@ -114,8 +132,9 @@ bool QuicChromiumPacketReader::ProcessReadResult(int result) { } void QuicChromiumPacketReader::OnReadComplete(int result) { - if (ProcessReadResult(result)) + if (ProcessReadResult(result)) { StartReading(); + } } } // namespace net diff --git a/naiveproxy/src/net/quic/quic_chromium_packet_reader.h b/naiveproxy/src/net/quic/quic_chromium_packet_reader.h index 513aeca782..40bbaacac7 100644 --- a/naiveproxy/src/net/quic/quic_chromium_packet_reader.h +++ b/naiveproxy/src/net/quic/quic_chromium_packet_reader.h @@ -77,6 +77,9 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketReader { quic::QuicTime yield_after_; scoped_refptr read_buffer_; NetLogWithSource net_log_; + // Stores whether receiving ECN is in the feature list to avoid accessing + // the feature list for every packet. + bool report_ecn_; base::WeakPtrFactory weak_factory_{this}; }; diff --git a/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc b/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc index 4964b544e4..00796a9dbc 100644 --- a/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc +++ b/naiveproxy/src/net/quic/quic_chromium_packet_writer.cc @@ -201,7 +201,7 @@ void QuicChromiumPacketWriter::SetWritable() { write_in_progress_ = false; } -absl::optional QuicChromiumPacketWriter::MessageTooBigErrorCode() const { +std::optional QuicChromiumPacketWriter::MessageTooBigErrorCode() const { return ERR_MSG_TOO_BIG; } diff --git a/naiveproxy/src/net/quic/quic_chromium_packet_writer.h b/naiveproxy/src/net/quic/quic_chromium_packet_writer.h index 96947056ea..f529254541 100644 --- a/naiveproxy/src/net/quic/quic_chromium_packet_writer.h +++ b/naiveproxy/src/net/quic/quic_chromium_packet_writer.h @@ -96,7 +96,7 @@ class NET_EXPORT_PRIVATE QuicChromiumPacketWriter const quic::QuicPacketWriterParams& params) override; bool IsWriteBlocked() const override; void SetWritable() override; - absl::optional MessageTooBigErrorCode() const override; + std::optional MessageTooBigErrorCode() const override; quic::QuicByteCount GetMaxPacketSize( const quic::QuicSocketAddress& peer_address) const override; bool SupportsReleaseTime() const override; diff --git a/naiveproxy/src/net/quic/quic_connectivity_monitor.cc b/naiveproxy/src/net/quic/quic_connectivity_monitor.cc index 1d369a6a48..6bc84cffe7 100644 --- a/naiveproxy/src/net/quic/quic_connectivity_monitor.cc +++ b/naiveproxy/src/net/quic/quic_connectivity_monitor.cc @@ -149,7 +149,7 @@ void QuicConnectivityMonitor::OnSessionResumedPostPathDegrading( num_all_degraded_sessions_ = 0u; num_sessions_active_during_current_speculative_connectivity_failure_ = - absl::nullopt; + std::nullopt; } void QuicConnectivityMonitor::OnSessionEncounteringWriteError( @@ -229,7 +229,7 @@ void QuicConnectivityMonitor::OnDefaultNetworkUpdated( active_sessions_.clear(); degrading_sessions_.clear(); num_sessions_active_during_current_speculative_connectivity_failure_ = - absl::nullopt; + std::nullopt; write_error_map_.clear(); quic_error_map_.clear(); } diff --git a/naiveproxy/src/net/quic/quic_connectivity_monitor.h b/naiveproxy/src/net/quic/quic_connectivity_monitor.h index 273e1b3a68..3003444b17 100644 --- a/naiveproxy/src/net/quic/quic_connectivity_monitor.h +++ b/naiveproxy/src/net/quic/quic_connectivity_monitor.h @@ -7,6 +7,7 @@ #include +#include "base/memory/raw_ptr.h" #include "base/numerics/clamped_math.h" #include "net/base/network_handle.h" #include "net/quic/quic_chromium_client_session.h" @@ -93,9 +94,11 @@ class NET_EXPORT_PRIVATE QuicConnectivityMonitor // handles::kInvalidNetworkHandle. handles::NetworkHandle default_network_; // Sessions that are currently degrading on the |default_network_|. - std::set degrading_sessions_; + std::set> + degrading_sessions_; // Sessions that are currently active on the |default_network_|. - std::set active_sessions_; + std::set> + active_sessions_; // Number of sessions that have been active or created during the period of // a speculative connectivity failure. @@ -104,7 +107,7 @@ class NET_EXPORT_PRIVATE QuicConnectivityMonitor // related packet write error, // - ends immediately by the detection of path recovery or a network change. // Use clamped math to cap number of sessions at INT_MAX. - absl::optional> + std::optional> num_sessions_active_during_current_speculative_connectivity_failure_; // Total number of sessions that has been degraded before any recovery, // including no longer active sessions. diff --git a/naiveproxy/src/net/quic/quic_context.h b/naiveproxy/src/net/quic/quic_context.h index aaa6b3edb2..231da97b1c 100644 --- a/naiveproxy/src/net/quic/quic_context.h +++ b/naiveproxy/src/net/quic/quic_context.h @@ -200,11 +200,11 @@ struct NET_EXPORT QuicParams { // (best effort). int ios_network_service_type = 0; // Delay for the 1st time the alternative service is marked broken. - absl::optional initial_delay_for_broken_alternative_service; + std::optional initial_delay_for_broken_alternative_service; // If true, the delay for broke alternative service would be initial_delay * // (1 << broken_count). Otherwise, the delay would be initial_delay, 5min, // 10min and so on. - absl::optional exponential_backoff_on_initial_delay; + std::optional exponential_backoff_on_initial_delay; // If true, delay main job even the request can be sent immediately on an // available SPDY session. bool delay_main_job_with_available_spdy_session = false; diff --git a/naiveproxy/src/net/quic/quic_http_stream.cc b/naiveproxy/src/net/quic/quic_http_stream.cc index 1cfbbd6998..23a1ac421c 100644 --- a/naiveproxy/src/net/quic/quic_http_stream.cc +++ b/naiveproxy/src/net/quic/quic_http_stream.cc @@ -350,14 +350,14 @@ base::StringPiece QuicHttpStream::GetAcceptChViaAlps() const { return session()->GetAcceptChViaAlps(url::SchemeHostPort(request_info_->url)); } -absl::optional QuicHttpStream::GetQuicErrorCode() const { +std::optional QuicHttpStream::GetQuicErrorCode() const { if (stream_) { return stream_->connection_error(); } return connection_error_; } -absl::optional +std::optional QuicHttpStream::GetQuicRstStreamErrorCode() const { if (stream_) { return stream_->stream_error(); diff --git a/naiveproxy/src/net/quic/quic_http_stream.h b/naiveproxy/src/net/quic/quic_http_stream.h index 6a04f07256..1f3591b17f 100644 --- a/naiveproxy/src/net/quic/quic_http_stream.h +++ b/naiveproxy/src/net/quic/quic_http_stream.h @@ -75,8 +75,8 @@ class NET_EXPORT_PRIVATE QuicHttpStream : public MultiplexedHttpStream { void SetRequestIdempotency(Idempotency idempotency) override; const std::set& GetDnsAliases() const override; base::StringPiece GetAcceptChViaAlps() const override; - absl::optional GetQuicErrorCode() const override; - absl::optional GetQuicRstStreamErrorCode() + std::optional GetQuicErrorCode() const override; + std::optional GetQuicRstStreamErrorCode() const override; static HttpConnectionInfo ConnectionInfoFromQuicVersion( @@ -204,8 +204,8 @@ class NET_EXPORT_PRIVATE QuicHttpStream : public MultiplexedHttpStream { // the default value of false. bool closed_is_first_stream_ = false; - absl::optional connection_error_; - absl::optional stream_error_; + std::optional connection_error_; + std::optional stream_error_; // The caller's callback to be used for asynchronous operations. CompletionOnceCallback callback_; diff --git a/naiveproxy/src/net/quic/quic_proxy_client_socket.cc b/naiveproxy/src/net/quic/quic_proxy_client_socket.cc index 4ad1a57cb3..83fdb1fb97 100644 --- a/naiveproxy/src/net/quic/quic_proxy_client_socket.cc +++ b/naiveproxy/src/net/quic/quic_proxy_client_socket.cc @@ -372,7 +372,7 @@ int QuicProxyClientSocket::DoSendRequest() { request_line, &request_.extra_headers); spdy::Http2HeaderBlock headers; - CreateSpdyHeadersFromHttpRequest(request_, absl::nullopt, + CreateSpdyHeadersFromHttpRequest(request_, std::nullopt, request_.extra_headers, &headers); return stream_->WriteHeaders(std::move(headers), false, nullptr); diff --git a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc new file mode 100644 index 0000000000..723625d42e --- /dev/null +++ b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.cc @@ -0,0 +1,152 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/quic_proxy_datagram_client_socket.h" + +#include "net/base/net_errors.h" + +namespace net { + +// TODO(crbug.com/1524411) Add net log begin event to constructor. +QuicProxyDatagramClientSocket::QuicProxyDatagramClientSocket( + const NetLogWithSource& source_net_log, + url::SchemeHostPort destination) + : net_log_(NetLogWithSource::Make( + source_net_log.net_log(), + NetLogSourceType::QUIC_PROXY_DATAGRAM_CLIENT_SOCKET)), + destination_(std::move(destination)) {} + +QuicProxyDatagramClientSocket::~QuicProxyDatagramClientSocket() {} + +int QuicProxyDatagramClientSocket::ConnectViaStream( + const IPEndPoint& local_address, + const IPEndPoint& proxy_peer_address, + std::unique_ptr stream, + CompletionOnceCallback callback) { + CHECK(!stream_); + local_address_ = local_address; + proxy_peer_address_ = proxy_peer_address; + stream_ = std::move(stream); + // TODO(crbug.com/1524411) Implement method. + return OK; +} + +int QuicProxyDatagramClientSocket::Connect(const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectAsync( + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingDefaultNetworkAsync( + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingNetwork( + handles::NetworkHandle network, + const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingDefaultNetwork( + const IPEndPoint& address) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::ConnectUsingNetworkAsync( + handles::NetworkHandle network, + const IPEndPoint& address, + CompletionOnceCallback callback) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411) Implement method. +handles::NetworkHandle QuicProxyDatagramClientSocket::GetBoundNetwork() const { + return handles::kInvalidNetworkHandle; +} + +// TODO(crbug.com/1524411): Implement method. +void QuicProxyDatagramClientSocket::ApplySocketTag(const SocketTag& tag) {} + +int QuicProxyDatagramClientSocket::SetMulticastInterface( + uint32_t interface_index) { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +void QuicProxyDatagramClientSocket::SetIOSNetworkServiceType( + int ios_network_service_type) {} + +void QuicProxyDatagramClientSocket::Close() {} + +int QuicProxyDatagramClientSocket::GetPeerAddress(IPEndPoint* address) const { + *address = proxy_peer_address_; + return OK; +} + +int QuicProxyDatagramClientSocket::GetLocalAddress(IPEndPoint* address) const { + *address = local_address_; + return OK; +} + +void QuicProxyDatagramClientSocket::UseNonBlockingIO() { + NOTREACHED(); +} + +int QuicProxyDatagramClientSocket::SetDoNotFragment() { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +int QuicProxyDatagramClientSocket::SetRecvTos() { + NOTREACHED(); + return ERR_NOT_IMPLEMENTED; +} + +void QuicProxyDatagramClientSocket::SetMsgConfirm(bool confirm) { + NOTREACHED(); +} + +const NetLogWithSource& QuicProxyDatagramClientSocket::NetLog() const { + return net_log_; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::Write( + IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::SetReceiveBufferSize(int32_t size) { + return ERR_NOT_IMPLEMENTED; +} + +// TODO(crbug.com/1524411): Implement method. +int QuicProxyDatagramClientSocket::SetSendBufferSize(int32_t size) { + return ERR_NOT_IMPLEMENTED; +} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h new file mode 100644 index 0000000000..53bda7fcf2 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_proxy_datagram_client_socket.h @@ -0,0 +1,102 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ +#define NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ + +#include + +#include "net/base/ip_endpoint.h" +#include "net/base/net_export.h" +#include "net/log/net_log.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/quic_chromium_client_stream.h" +#include "net/socket/datagram_client_socket.h" +#include "net/socket/udp_socket.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "url/scheme_host_port.h" + +namespace net { + +// A client socket that uses a QUIC proxy as the transport layer. +// +// Given that DatagramClientSocket class contains numerous methods tailored for +// UDP, many methods from DatagramClientSocket are left as stubs. +// ConnectViaStream is used to connect this socket over the provided QUIC stream +// to send and receive datagrams. +class NET_EXPORT_PRIVATE QuicProxyDatagramClientSocket + : public DatagramClientSocket { + public: + // Initializes a QuicProxyDatagramClientSocket with the provided network + // log (source_net_log) and destination URL. The destination parameter + // specifies the target server (including the scheme, hostname, and port + // number) to which datagrams will be sent. + QuicProxyDatagramClientSocket(const NetLogWithSource& source_net_log, + url::SchemeHostPort destination); + + QuicProxyDatagramClientSocket(const QuicProxyDatagramClientSocket&) = delete; + QuicProxyDatagramClientSocket& operator=( + const QuicProxyDatagramClientSocket&) = delete; + + ~QuicProxyDatagramClientSocket() override; + + // Connect this socket over the given QUIC stream, using the `destination_` + // and local and proxy peer addresses. The socket has no true peer + // address since it is connected over a proxy and the proxy performs the + // hostname resolution. Instead `proxy_peer_address_` is the peer to which the + // underlying socket is connected. + int ConnectViaStream(const IPEndPoint& local_address, + const IPEndPoint& proxy_peer_address, + std::unique_ptr stream, + CompletionOnceCallback callback); + + // DatagramClientSocket implementation. + int Connect(const IPEndPoint& address) override; + int ConnectUsingNetwork(handles::NetworkHandle network, + const IPEndPoint& address) override; + int ConnectUsingDefaultNetwork(const IPEndPoint& address) override; + int ConnectAsync(const IPEndPoint& address, + CompletionOnceCallback callback) override; + int ConnectUsingNetworkAsync(handles::NetworkHandle network, + const IPEndPoint& address, + CompletionOnceCallback callback) override; + int ConnectUsingDefaultNetworkAsync(const IPEndPoint& address, + CompletionOnceCallback callback) override; + handles::NetworkHandle GetBoundNetwork() const override; + void ApplySocketTag(const SocketTag& tag) override; + int SetMulticastInterface(uint32_t interface_index) override; + void SetIOSNetworkServiceType(int ios_network_service_type) override; + + // DatagramSocket implementation. + void Close() override; + int GetPeerAddress(IPEndPoint* address) const override; + int GetLocalAddress(IPEndPoint* address) const override; + void UseNonBlockingIO() override; + int SetDoNotFragment() override; + int SetRecvTos() override; + void SetMsgConfirm(bool confirm) override; + const NetLogWithSource& NetLog() const override; + + // Socket implementation. + int Read(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback) override; + int Write(IOBuffer* buf, + int buf_len, + CompletionOnceCallback callback, + const NetworkTrafficAnnotationTag& traffic_annotation) override; + int SetReceiveBufferSize(int32_t size) override; + int SetSendBufferSize(int32_t size) override; + + private: + NetLogWithSource net_log_; + IPEndPoint local_address_; + IPEndPoint proxy_peer_address_; + std::unique_ptr stream_; + url::SchemeHostPort destination_; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_PROXY_DATAGRAM_CLIENT_SOCKET_H_ diff --git a/naiveproxy/src/net/quic/quic_session_key.cc b/naiveproxy/src/net/quic/quic_session_key.cc index 6de1ad6c68..93f09290c1 100644 --- a/naiveproxy/src/net/quic/quic_session_key.cc +++ b/naiveproxy/src/net/quic/quic_session_key.cc @@ -4,9 +4,16 @@ #include "net/quic/quic_session_key.h" -#include "base/feature_list.h" -#include "net/base/features.h" +#include + +#include "net/base/host_port_pair.h" +#include "net/base/network_anonymization_key.h" +#include "net/base/privacy_mode.h" +#include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" +#include "net/socket/socket_tag.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" namespace net { @@ -15,6 +22,8 @@ QuicSessionKey::QuicSessionKey() = default; QuicSessionKey::QuicSessionKey( const HostPortPair& host_port_pair, PrivacyMode privacy_mode, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -22,6 +31,8 @@ QuicSessionKey::QuicSessionKey( : QuicSessionKey(host_port_pair.host(), host_port_pair.port(), privacy_mode, + proxy_chain, + session_usage, socket_tag, network_anonymization_key, secure_dns_policy, @@ -31,6 +42,8 @@ QuicSessionKey::QuicSessionKey( const std::string& host, uint16_t port, PrivacyMode privacy_mode, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -38,6 +51,8 @@ QuicSessionKey::QuicSessionKey( : QuicSessionKey( // TODO(crbug.com/1103350): Handle non-boolean privacy modes. quic::QuicServerId(host, port, privacy_mode != PRIVACY_MODE_DISABLED), + proxy_chain, + session_usage, socket_tag, network_anonymization_key, secure_dns_policy, @@ -45,11 +60,15 @@ QuicSessionKey::QuicSessionKey( QuicSessionKey::QuicSessionKey( const quic::QuicServerId& server_id, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, bool require_dns_https_alpn) : server_id_(server_id), + proxy_chain_(proxy_chain), + session_usage_(session_usage), socket_tag_(socket_tag), network_anonymization_key_( NetworkAnonymizationKey::IsPartitioningEnabled() @@ -61,14 +80,17 @@ QuicSessionKey::QuicSessionKey( QuicSessionKey::QuicSessionKey(const QuicSessionKey& other) = default; bool QuicSessionKey::operator<(const QuicSessionKey& other) const { - return std::tie(server_id_, socket_tag_, network_anonymization_key_, - secure_dns_policy_, require_dns_https_alpn_) < - std::tie(other.server_id_, other.socket_tag_, - other.network_anonymization_key_, other.secure_dns_policy_, - other.require_dns_https_alpn_); + return std::tie(server_id_, proxy_chain_, session_usage_, socket_tag_, + network_anonymization_key_, secure_dns_policy_, + require_dns_https_alpn_) < + std::tie(other.server_id_, other.proxy_chain_, other.session_usage_, + other.socket_tag_, other.network_anonymization_key_, + other.secure_dns_policy_, other.require_dns_https_alpn_); } bool QuicSessionKey::operator==(const QuicSessionKey& other) const { - return server_id_ == other.server_id_ && socket_tag_ == other.socket_tag_ && + return server_id_ == other.server_id_ && proxy_chain_ == other.proxy_chain_ && + session_usage_ == other.session_usage_ && + socket_tag_ == other.socket_tag_ && network_anonymization_key_ == other.network_anonymization_key_ && secure_dns_policy_ == other.secure_dns_policy_ && require_dns_https_alpn_ == other.require_dns_https_alpn_; @@ -78,6 +100,8 @@ bool QuicSessionKey::CanUseForAliasing(const QuicSessionKey& other) const { return server_id_.privacy_mode_enabled() == other.server_id_.privacy_mode_enabled() && socket_tag_ == other.socket_tag_ && + proxy_chain_ == other.proxy_chain_ && + session_usage_ == other.session_usage_ && network_anonymization_key_ == other.network_anonymization_key_ && secure_dns_policy_ == other.secure_dns_policy_ && require_dns_https_alpn_ == other.require_dns_https_alpn_; diff --git a/naiveproxy/src/net/quic/quic_session_key.h b/naiveproxy/src/net/quic/quic_session_key.h index c8ce63b34d..69d950b538 100644 --- a/naiveproxy/src/net/quic/quic_session_key.h +++ b/naiveproxy/src/net/quic/quic_session_key.h @@ -8,6 +8,8 @@ #include "net/base/host_port_pair.h" #include "net/base/network_anonymization_key.h" #include "net/base/privacy_mode.h" +#include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" #include "net/socket/socket_tag.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" @@ -21,6 +23,8 @@ class NET_EXPORT_PRIVATE QuicSessionKey { QuicSessionKey(); QuicSessionKey(const HostPortPair& host_port_pair, PrivacyMode privacy_mode, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -28,11 +32,15 @@ class NET_EXPORT_PRIVATE QuicSessionKey { QuicSessionKey(const std::string& host, uint16_t port, PrivacyMode privacy_mode, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, bool require_dns_https_alpn); QuicSessionKey(const quic::QuicServerId& server_id, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -63,6 +71,10 @@ class NET_EXPORT_PRIVATE QuicSessionKey { const quic::QuicServerId& server_id() const { return server_id_; } + const ProxyChain& proxy_chain() const { return proxy_chain_; } + + SessionUsage session_usage() const { return session_usage_; } + SocketTag socket_tag() const { return socket_tag_; } const NetworkAnonymizationKey& network_anonymization_key() const { @@ -75,6 +87,8 @@ class NET_EXPORT_PRIVATE QuicSessionKey { private: quic::QuicServerId server_id_; + ProxyChain proxy_chain_; + SessionUsage session_usage_; SocketTag socket_tag_; // Used to separate requests made in different contexts. NetworkAnonymizationKey network_anonymization_key_; diff --git a/naiveproxy/src/net/quic/quic_session_pool.cc b/naiveproxy/src/net/quic/quic_session_pool.cc index bf1b3c4980..f0e461e65e 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.cc +++ b/naiveproxy/src/net/quic/quic_session_pool.cc @@ -13,7 +13,6 @@ #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/location.h" -#include "base/memory/memory_pressure_monitor.h" #include "base/memory/raw_ptr.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_functions.h" @@ -26,8 +25,6 @@ #include "base/strings/stringprintf.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" -#include "base/time/default_clock.h" -#include "base/time/default_tick_clock.h" #include "base/values.h" #include "crypto/openssl_util.h" #include "net/base/address_list.h" @@ -35,6 +32,7 @@ #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/base/network_anonymization_key.h" +#include "net/base/session_usage.h" #include "net/base/trace_constants.h" #include "net/base/tracing.h" #include "net/cert/cert_verifier.h" @@ -53,8 +51,10 @@ #include "net/quic/quic_chromium_packet_writer.h" #include "net/quic/quic_context.h" #include "net/quic/quic_crypto_client_stream_factory.h" -#include "net/quic/quic_http_stream.h" #include "net/quic/quic_server_info.h" +#include "net/quic/quic_session_key.h" +#include "net/quic/quic_session_pool_direct_job.h" +#include "net/quic/quic_session_pool_job.h" #include "net/socket/client_socket_factory.h" #include "net/socket/next_proto.h" #include "net/socket/socket_performance_watcher.h" @@ -62,12 +62,12 @@ #include "net/socket/udp_client_socket.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/null_decrypter.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/proof_verifier.h" -#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/platform/api/quic_flags.h" +#include "net/traffic_annotation/network_traffic_annotation.h" #include "third_party/boringssl/src/include/openssl/aead.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -85,27 +85,6 @@ enum InitialRttEstimateSource { INITIAL_RTT_SOURCE_MAX, }; -enum class JobProtocolErrorLocation { - kSessionStartReadingFailedAsync = 0, - kSessionStartReadingFailedSync = 1, - kCreateSessionFailedAsync = 2, - kCreateSessionFailedSync = 3, - kCryptoConnectFailedSync = 4, - kCryptoConnectFailedAsync = 5, - kMaxValue = kCryptoConnectFailedAsync, -}; - -base::Value::Dict NetLogQuicSessionPoolJobParams( - const QuicSessionPool::QuicSessionAliasKey* key) { - return base::Value::Dict() - .Set("host", key->server_id().host()) - .Set("port", key->server_id().port()) - .Set("privacy_mode", - PrivacyModeToDebugString(key->session_key().privacy_mode())) - .Set("network_anonymization_key", - key->session_key().network_anonymization_key().ToDebugString()); -} - std::string QuicPlatformNotificationToString( QuicPlatformNotification notification) { switch (notification) { @@ -131,25 +110,6 @@ void HistogramCreateSessionFailure(enum CreateSessionFailure error) { CREATION_ERROR_MAX); } -void HistogramProtocolErrorLocation(enum JobProtocolErrorLocation location) { - UMA_HISTOGRAM_ENUMERATION("Net.QuicStreamFactory.DoConnectFailureLocation", - location); -} - -void LogConnectionIpPooling(bool pooled) { - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionIpPooled", pooled); -} - -void LogStaleConnectionTime(base::TimeTicks start_time) { - UMA_HISTOGRAM_TIMES("Net.QuicSession.StaleConnectionTime", - base::TimeTicks::Now() - start_time); -} - -void LogValidConnectionTime(base::TimeTicks start_time) { - UMA_HISTOGRAM_TIMES("Net.QuicSession.ValidConnectionTime", - base::TimeTicks::Now() - start_time); -} - void SetInitialRttEstimate(base::TimeDelta estimate, enum InitialRttEstimateSource source, quic::QuicConfig* config) { @@ -196,741 +156,6 @@ std::set HostsFromOrigins(std::set origins) { } // namespace -// Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many -// consumers are using it currently. When the last reference is freed, the -// QuicCryptoClientConfigHandle informs the owning QuicSessionPool, moves it -// into an MRU cache. -class QuicSessionPool::QuicCryptoClientConfigOwner { - public: - QuicCryptoClientConfigOwner( - std::unique_ptr proof_verifier, - std::unique_ptr session_cache, - QuicSessionPool* quic_session_pool) - : config_(std::move(proof_verifier), std::move(session_cache)), - clock_(base::DefaultClock::GetInstance()), - quic_session_pool_(quic_session_pool) { - DCHECK(quic_session_pool_); - memory_pressure_listener_ = std::make_unique( - FROM_HERE, - base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure, - base::Unretained(this))); - if (quic_session_pool_->ssl_config_service_->GetSSLContextConfig() - .PostQuantumKeyAgreementEnabled()) { - config_.set_preferred_groups({SSL_GROUP_X25519_KYBER768_DRAFT00, - SSL_GROUP_X25519, SSL_GROUP_SECP256R1, - SSL_GROUP_SECP384R1}); - } - } - - QuicCryptoClientConfigOwner(const QuicCryptoClientConfigOwner&) = delete; - QuicCryptoClientConfigOwner& operator=(const QuicCryptoClientConfigOwner&) = - delete; - - ~QuicCryptoClientConfigOwner() { DCHECK_EQ(num_refs_, 0); } - - quic::QuicCryptoClientConfig* config() { return &config_; } - - int num_refs() const { return num_refs_; } - - QuicSessionPool* quic_session_pool() { return quic_session_pool_; } - - void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - quic::SessionCache* session_cache = config_.session_cache(); - if (!session_cache) { - return; - } - time_t now = clock_->Now().ToTimeT(); - uint64_t now_u64 = 0; - if (now > 0) { - now_u64 = static_cast(now); - } - switch (memory_pressure_level) { - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: - break; - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: - session_cache->RemoveExpiredEntries( - quic::QuicWallTime::FromUNIXSeconds(now_u64)); - break; - case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: - session_cache->Clear(); - break; - } - } - - private: - friend class CryptoClientConfigHandle; - - // Simple ref counting. Not using scoped_refptr allows for both keeping around - // an MRU cache of 0-reference objects, and DCHECKing that there are no - // outstanding referenced QuicCryptoClientConfigOwner on destruction. Private - // so that only CryptoClientConfigHandle can add and remove refs. - - void AddRef() { num_refs_++; } - - void ReleaseRef() { - DCHECK_GT(num_refs_, 0); - num_refs_--; - } - - int num_refs_ = 0; - quic::QuicCryptoClientConfig config_; - raw_ptr clock_; - std::unique_ptr memory_pressure_listener_; - const raw_ptr quic_session_pool_; -}; - -// Class that owns a reference to a QuicCryptoClientConfigOwner. Handles -// incrementing the refcount on construction, and decrementing it on -// destruction. -class QuicSessionPool::CryptoClientConfigHandle - : public QuicCryptoClientConfigHandle { - public: - explicit CryptoClientConfigHandle( - const QuicCryptoClientConfigMap::iterator& map_iterator) - : map_iterator_(map_iterator) { - DCHECK_GE(map_iterator_->second->num_refs(), 0); - map_iterator->second->AddRef(); - } - - CryptoClientConfigHandle(const CryptoClientConfigHandle& other) - : CryptoClientConfigHandle(other.map_iterator_) {} - - CryptoClientConfigHandle& operator=(const CryptoClientConfigHandle&) = delete; - - ~CryptoClientConfigHandle() override { - DCHECK_GT(map_iterator_->second->num_refs(), 0); - map_iterator_->second->ReleaseRef(); - if (map_iterator_->second->num_refs() == 0) { - map_iterator_->second->quic_session_pool()->OnAllCryptoClientRefReleased( - map_iterator_); - } - } - - quic::QuicCryptoClientConfig* GetConfig() const override { - return map_iterator_->second->config(); - } - - private: - QuicCryptoClientConfigMap::iterator map_iterator_; -}; - -// Responsible for creating a new QUIC session to the specified server, and -// for notifying any associated requests when complete. |client_config_handle| -// is not actually used, but serves to keep the corresponding CryptoClientConfig -// alive until the Job completes. -class QuicSessionPool::Job { - public: - Job(QuicSessionPool* pool, - quic::ParsedQuicVersion quic_version, - HostResolver* host_resolver, - const QuicSessionAliasKey& key, - std::unique_ptr client_config_handle, - bool was_alternative_service_recently_broken, - bool retry_on_alternate_network_before_handshake, - RequestPriority priority, - bool use_dns_aliases, - bool require_dns_https_alpn, - int cert_verify_flags, - const NetLogWithSource& net_log); - - Job(const Job&) = delete; - Job& operator=(const Job&) = delete; - - ~Job(); - - int Run(CompletionOnceCallback callback); - - int DoLoop(int rv); - int DoResolveHost(); - int DoResolveHostComplete(int rv); - int DoCreateSession(); - int DoCreateSessionComplete(int rv); - int DoConnect(int rv); - int DoConfirmConnection(int rv); - - void OnCreateSessionComplete(int rv); - void OnResolveHostComplete(int rv); - void OnCryptoConnectComplete(int rv); - - const QuicSessionAliasKey& key() const { return key_; } - - const NetLogWithSource& net_log() const { return net_log_; } - - base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } - - void PopulateNetErrorDetails(NetErrorDetails* details) const; - - void AddRequest(QuicSessionRequest* request) { - stream_requests_.insert(request); - if (!host_resolution_finished_) { - request->ExpectOnHostResolution(); - } - // Callers do not need to wait for OnQuicSessionCreationComplete if the - // kAsyncQuicSession flag is not set because session creation will be fully - // synchronous, so no need to call ExpectQuicSessionCreation. - if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession) && - !session_creation_finished_) { - request->ExpectQuicSessionCreation(); - } - } - - void RemoveRequest(QuicSessionRequest* request) { - auto request_iter = stream_requests_.find(request); - DCHECK(request_iter != stream_requests_.end()); - stream_requests_.erase(request_iter); - } - - void SetPriority(RequestPriority priority) { - if (priority_ == priority) { - return; - } - - priority_ = priority; - if (resolve_host_request_ && !host_resolution_finished_) { - resolve_host_request_->ChangeRequestPriority(priority); - } - } - - const std::set& stream_requests() { - return stream_requests_; - } - - RequestPriority priority() const { return priority_; } - - private: - enum IoState { - STATE_NONE, - STATE_RESOLVE_HOST, - STATE_RESOLVE_HOST_COMPLETE, - STATE_CREATE_SESSION, - STATE_CREATE_SESSION_COMPLETE, - STATE_CONNECT, - STATE_CONFIRM_CONNECTION, - }; - - void CloseStaleHostConnection() { - DVLOG(1) << "Closing connection from stale host."; - if (session_) { - QuicChromiumClientSession* session = session_; - session_ = nullptr; - // Use ERR_FAILED instead of ERR_ABORTED out of paranoia - ERR_ABORTED - // should only be used when the next layer up cancels a request, and has - // special semantic meaning for some consumers when they see it. - session->CloseSessionOnErrorLater( - ERR_FAILED, quic::QUIC_STALE_CONNECTION_CANCELLED, - quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - } - } - - // Returns whether the client should be SVCB-optional when connecting to - // `results`. - bool IsSvcbOptional( - base::span results) const { - // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all - // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of - // draft-ietf-dnsop-svcb-https-11. - if (!pool_->ssl_config_service_->GetSSLContextConfig().ech_enabled) { - return true; // ECH is not supported for this request. - } - - return !HostResolver::AllProtocolEndpointsHaveEch(results); - } - - // Returns the QUIC version that would be used with `endpoint_result`, or - // `quic::ParsedQuicVersion::Unsupported()` if `endpoint_result` cannot be - // used with QUIC. - quic::ParsedQuicVersion SelectQuicVersion( - const HostResolverEndpointResult& endpoint_result, - bool svcb_optional) const { - // TODO(davidben): `require_dns_https_alpn_` only exists to be `DCHECK`ed - // for consistency against `quic_version_`. Remove the parameter? - DCHECK_EQ(require_dns_https_alpn_, !quic_version_.IsKnown()); - - if (endpoint_result.metadata.supported_protocol_alpns.empty()) { - // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB - // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc, - // use it in SVCB-optional mode. Otherwise, `endpoint_result` is not - // eligible for QUIC. - return svcb_optional ? quic_version_ - : quic::ParsedQuicVersion::Unsupported(); - } - - // Otherwise, `endpoint_result` came from an HTTPS/SVCB record. We can use - // QUIC if a suitable match is found in the record's ALPN list. - // Additionally, if this connection attempt came from Alt-Svc, the DNS - // result must be consistent with it. See - // https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-11.html#name-interaction-with-alt-svc - if (quic_version_.IsKnown()) { - std::string expected_alpn = quic::AlpnForVersion(quic_version_); - if (base::Contains(endpoint_result.metadata.supported_protocol_alpns, - quic::AlpnForVersion(quic_version_))) { - return quic_version_; - } - return quic::ParsedQuicVersion::Unsupported(); - } - - for (const auto& alpn : endpoint_result.metadata.supported_protocol_alpns) { - for (const auto& supported_version : pool_->supported_versions()) { - if (alpn == AlpnForVersion(supported_version)) { - return supported_version; - } - } - } - - return quic::ParsedQuicVersion::Unsupported(); - } - - void LogStaleAndFreshHostMatched(bool matched) { - if (matched) { - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_POOL_JOB_STALE_HOST_RESOLUTION_MATCHED); - } else { - net_log_.AddEvent( - NetLogEventType:: - QUIC_SESSION_POOL_JOB_STALE_HOST_RESOLUTION_NO_MATCH); - } - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleAndFreshHostMatched", matched); - } - - IoState io_state_ = STATE_RESOLVE_HOST; - raw_ptr pool_; - quic::ParsedQuicVersion quic_version_; - quic::ParsedQuicVersion quic_version_used_ = - quic::ParsedQuicVersion::Unsupported(); - raw_ptr host_resolver_; - const QuicSessionAliasKey key_; - const std::unique_ptr client_config_handle_; - RequestPriority priority_; - const bool use_dns_aliases_; - const bool require_dns_https_alpn_; - const int cert_verify_flags_; - const bool was_alternative_service_recently_broken_; - const bool retry_on_alternate_network_before_handshake_; - const NetLogWithSource net_log_; - bool host_resolution_finished_ = false; - bool session_creation_finished_ = false; - bool connection_retried_ = false; - raw_ptr session_ = nullptr; - HostResolverEndpointResult endpoint_result_; - // If connection migraiton is supported, |network_| denotes the network on - // which |session_| is created. - handles::NetworkHandle network_; - CompletionOnceCallback host_resolution_callback_; - CompletionOnceCallback callback_; - std::unique_ptr resolve_host_request_; - base::TimeTicks dns_resolution_start_time_; - base::TimeTicks dns_resolution_end_time_; - base::TimeTicks quic_connection_start_time_; - std::set stream_requests_; - base::WeakPtrFactory weak_factory_{this}; -}; - -QuicSessionPool::Job::Job( - QuicSessionPool* pool, - quic::ParsedQuicVersion quic_version, - HostResolver* host_resolver, - const QuicSessionAliasKey& key, - std::unique_ptr client_config_handle, - bool was_alternative_service_recently_broken, - bool retry_on_alternate_network_before_handshake, - RequestPriority priority, - bool use_dns_aliases, - bool require_dns_https_alpn, - int cert_verify_flags, - const NetLogWithSource& net_log) - : pool_(pool), - quic_version_(quic_version), - host_resolver_(host_resolver), - key_(key), - client_config_handle_(std::move(client_config_handle)), - priority_(priority), - use_dns_aliases_(use_dns_aliases), - require_dns_https_alpn_(require_dns_https_alpn), - cert_verify_flags_(cert_verify_flags), - was_alternative_service_recently_broken_( - was_alternative_service_recently_broken), - retry_on_alternate_network_before_handshake_( - retry_on_alternate_network_before_handshake), - net_log_(NetLogWithSource::Make(net_log.net_log(), - NetLogSourceType::QUIC_SESSION_POOL_JOB)), - network_(handles::kInvalidNetworkHandle) { - DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn); - net_log_.BeginEvent(NetLogEventType::QUIC_SESSION_POOL_JOB, - [&] { return NetLogQuicSessionPoolJobParams(&key_); }); - // Associate |net_log_| with |net_log|. - net_log_.AddEventReferencingSource( - NetLogEventType::QUIC_SESSION_POOL_JOB_BOUND_TO_HTTP_STREAM_JOB, - net_log.source()); - net_log.AddEventReferencingSource( - NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_SESSION_POOL_JOB, - net_log_.source()); -} - -QuicSessionPool::Job::~Job() { - net_log_.EndEvent(NetLogEventType::QUIC_SESSION_POOL_JOB); - // If |this| is destroyed in QuicSessionPool's destructor, |callback_| is - // non-null. -} - -int QuicSessionPool::Job::Run(CompletionOnceCallback callback) { - int rv = DoLoop(OK); - if (rv == ERR_IO_PENDING) { - callback_ = std::move(callback); - } - - return rv > 0 ? OK : rv; -} - -int QuicSessionPool::Job::DoLoop(int rv) { - TRACE_EVENT0(NetTracingCategory(), "QuicSessionPool::Job::DoLoop"); - - do { - IoState state = io_state_; - io_state_ = STATE_NONE; - switch (state) { - case STATE_RESOLVE_HOST: - CHECK_EQ(OK, rv); - rv = DoResolveHost(); - break; - case STATE_RESOLVE_HOST_COMPLETE: - rv = DoResolveHostComplete(rv); - break; - case STATE_CREATE_SESSION: - rv = DoCreateSession(); - break; - case STATE_CREATE_SESSION_COMPLETE: - rv = DoCreateSessionComplete(rv); - break; - case STATE_CONNECT: - rv = DoConnect(rv); - break; - case STATE_CONFIRM_CONNECTION: - rv = DoConfirmConnection(rv); - break; - default: - NOTREACHED() << "io_state_: " << io_state_; - break; - } - } while (io_state_ != STATE_NONE && rv != ERR_IO_PENDING); - return rv; -} - -void QuicSessionPool::Job::OnResolveHostComplete(int rv) { - DCHECK(!host_resolution_finished_); - io_state_ = STATE_RESOLVE_HOST_COMPLETE; - rv = DoLoop(rv); - - for (auto* request : stream_requests_) { - request->OnHostResolutionComplete(rv); - } - - if (rv != ERR_IO_PENDING && !callback_.is_null()) { - std::move(callback_).Run(rv); - } -} - -void QuicSessionPool::Job::OnCryptoConnectComplete(int rv) { - // This early return will be triggered when CloseSessionOnError is called - // before crypto handshake has completed. - if (!session_) { - LogStaleConnectionTime(quic_connection_start_time_); - return; - } - - if (rv == ERR_QUIC_PROTOCOL_ERROR) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCryptoConnectFailedAsync); - } - - io_state_ = STATE_CONFIRM_CONNECTION; - rv = DoLoop(rv); - if (rv != ERR_IO_PENDING && !callback_.is_null()) { - std::move(callback_).Run(rv); - } -} - -void QuicSessionPool::Job::PopulateNetErrorDetails( - NetErrorDetails* details) const { - if (!session_) { - return; - } - details->connection_info = QuicHttpStream::ConnectionInfoFromQuicVersion( - session_->connection()->version()); - details->quic_connection_error = session_->error(); -} - -int QuicSessionPool::Job::DoResolveHost() { - dns_resolution_start_time_ = base::TimeTicks::Now(); - - io_state_ = STATE_RESOLVE_HOST_COMPLETE; - - HostResolver::ResolveHostParameters parameters; - parameters.initial_priority = priority_; - parameters.secure_dns_policy = key_.session_key().secure_dns_policy(); - resolve_host_request_ = host_resolver_->CreateRequest( - key_.destination(), key_.session_key().network_anonymization_key(), - net_log_, parameters); - // Unretained is safe because |this| owns the request, ensuring cancellation - // on destruction. - return resolve_host_request_->Start(base::BindOnce( - &QuicSessionPool::Job::OnResolveHostComplete, base::Unretained(this))); -} - -int QuicSessionPool::Job::DoResolveHostComplete(int rv) { - host_resolution_finished_ = true; - dns_resolution_end_time_ = base::TimeTicks::Now(); - if (rv != OK) { - return rv; - } - - DCHECK(!pool_->HasActiveSession(key_.session_key())); - - // Inform the pool of this resolution, which will set up - // a session alias, if possible. - const bool svcb_optional = - IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); - for (const auto& endpoint : *resolve_host_request_->GetEndpointResults()) { - // Only consider endpoints that would have been eligible for QUIC. - if (!SelectQuicVersion(endpoint, svcb_optional).IsKnown()) { - continue; - } - if (pool_->HasMatchingIpSession( - key_, endpoint.ip_endpoints, - *resolve_host_request_->GetDnsAliasResults(), use_dns_aliases_)) { - LogConnectionIpPooling(true); - return OK; - } - } - io_state_ = STATE_CREATE_SESSION; - return OK; -} - -void QuicSessionPool::Job::OnCreateSessionComplete(int rv) { - if (rv != OK) { - DCHECK(!session_); - if (rv == ERR_QUIC_PROTOCOL_ERROR) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCreateSessionFailedAsync); - } - for (auto* request : stream_requests_) { - request->OnQuicSessionCreationComplete(rv); - } - if (!callback_.is_null()) { - std::move(callback_).Run(rv); - } - return; - } - DCHECK(session_); - DVLOG(1) << "Created session on network: " << network_; - io_state_ = STATE_CREATE_SESSION_COMPLETE; - rv = DoLoop(rv); - - for (auto* request : stream_requests_) { - request->OnQuicSessionCreationComplete(rv); - } - - if (rv != ERR_IO_PENDING && !callback_.is_null()) { - std::move(callback_).Run(rv); - } -} - -int QuicSessionPool::Job::DoCreateSession() { - // TODO(https://crbug.com/1416409): This logic only knows how to try one - // endpoint result. - bool svcb_optional = - IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); - bool found = false; - for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) { - quic::ParsedQuicVersion version = - SelectQuicVersion(candidate, svcb_optional); - if (version.IsKnown()) { - found = true; - quic_version_used_ = version; - endpoint_result_ = candidate; - break; - } - } - if (!found) { - return ERR_DNS_NO_MATCHING_SUPPORTED_ALPN; - } - - quic_connection_start_time_ = base::TimeTicks::Now(); - DCHECK(dns_resolution_end_time_ != base::TimeTicks()); - io_state_ = STATE_CREATE_SESSION_COMPLETE; - bool require_confirmation = was_alternative_service_recently_broken_; - net_log_.AddEntryWithBoolParams( - NetLogEventType::QUIC_SESSION_POOL_JOB_CONNECT, NetLogEventPhase::BEGIN, - "require_confirmation", require_confirmation); - - DCHECK_NE(quic_version_used_, quic::ParsedQuicVersion::Unsupported()); - if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { - return pool_->CreateSessionAsync( - base::BindOnce(&QuicSessionPool::Job::OnCreateSessionComplete, - GetWeakPtr()), - key_, quic_version_used_, cert_verify_flags_, require_confirmation, - endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, - net_log_, &session_, &network_); - } - int rv = pool_->CreateSessionSync( - key_, quic_version_used_, cert_verify_flags_, require_confirmation, - endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, - net_log_, &session_, &network_); - - DVLOG(1) << "Created session on network: " << network_; - - if (rv == ERR_QUIC_PROTOCOL_ERROR) { - DCHECK(!session_); - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCreateSessionFailedSync); - } - - return rv; -} -int QuicSessionPool::Job::DoCreateSessionComplete(int rv) { - session_creation_finished_ = true; - if (rv != OK) { - return rv; - } - io_state_ = STATE_CONNECT; - if (!session_->connection()->connected()) { - return ERR_CONNECTION_CLOSED; - } - - session_->StartReading(); - if (!session_->connection()->connected()) { - if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kSessionStartReadingFailedAsync); - } else { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kSessionStartReadingFailedSync); - } - return ERR_QUIC_PROTOCOL_ERROR; - } - return OK; -} - -int QuicSessionPool::Job::DoConnect(int rv) { - if (rv != OK) { - return rv; - } - DCHECK(session_); - io_state_ = STATE_CONFIRM_CONNECTION; - rv = session_->CryptoConnect(base::BindOnce( - &QuicSessionPool::Job::OnCryptoConnectComplete, GetWeakPtr())); - - if (rv != ERR_IO_PENDING) { - LogValidConnectionTime(quic_connection_start_time_); - } - - if (!session_->connection()->connected() && - session_->error() == quic::QUIC_PROOF_INVALID) { - return ERR_QUIC_HANDSHAKE_FAILED; - } - - if (rv == ERR_QUIC_PROTOCOL_ERROR) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCryptoConnectFailedSync); - } - - return rv; -} - -int QuicSessionPool::Job::DoConfirmConnection(int rv) { - UMA_HISTOGRAM_TIMES("Net.QuicSession.TimeFromResolveHostToConfirmConnection", - base::TimeTicks::Now() - dns_resolution_start_time_); - net_log_.EndEvent(NetLogEventType::QUIC_SESSION_POOL_JOB_CONNECT); - - if (was_alternative_service_recently_broken_) { - UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectAfterBroken", rv == OK); - } - - if (retry_on_alternate_network_before_handshake_ && session_ && - !session_->OneRttKeysAvailable() && - network_ == pool_->default_network()) { - if (session_->error() == quic::QUIC_NETWORK_IDLE_TIMEOUT || - session_->error() == quic::QUIC_HANDSHAKE_TIMEOUT || - session_->error() == quic::QUIC_PACKET_WRITE_ERROR) { - // Retry the connection on an alternate network if crypto handshake failed - // with network idle time out or handshake time out. - DCHECK(network_ != handles::kInvalidNetworkHandle); - network_ = pool_->FindAlternateNetwork(network_); - connection_retried_ = network_ != handles::kInvalidNetworkHandle; - UMA_HISTOGRAM_BOOLEAN( - "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake", - connection_retried_); - UMA_HISTOGRAM_ENUMERATION( - "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake." - "FailedConnectionType", - NetworkChangeNotifier::GetNetworkConnectionType( - pool_->default_network()), - NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1); - if (connection_retried_) { - UMA_HISTOGRAM_ENUMERATION( - "Net.QuicStreamFactory.MigrationBeforeHandshake.NewConnectionType", - NetworkChangeNotifier::GetNetworkConnectionType(network_), - NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1); - net_log_.AddEvent( - NetLogEventType::QUIC_SESSION_POOL_JOB_RETRY_ON_ALTERNATE_NETWORK); - // Notify requests that connection on the default network failed. - for (auto* request : stream_requests_) { - request->OnConnectionFailedOnDefaultNetwork(); - } - DVLOG(1) << "Retry connection on alternate network: " << network_; - session_ = nullptr; - io_state_ = STATE_CREATE_SESSION; - return OK; - } - } - } - - if (connection_retried_) { - UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.MigrationBeforeHandshake2", - rv == OK); - if (rv == OK) { - UMA_HISTOGRAM_BOOLEAN( - "Net.QuicStreamFactory.NetworkChangeDuringMigrationBeforeHandshake", - network_ == pool_->default_network()); - } else { - base::UmaHistogramSparse( - "Net.QuicStreamFactory.MigrationBeforeHandshakeFailedReason", -rv); - } - } else if (network_ != handles::kInvalidNetworkHandle && - network_ != pool_->default_network()) { - UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.ConnectionOnNonDefaultNetwork", - rv == OK); - } - - if (rv != OK) { - return rv; - } - - DCHECK(!pool_->HasActiveSession(key_.session_key())); - // There may well now be an active session for this IP. If so, use the - // existing session instead. - if (pool_->HasMatchingIpSession( - key_, {ToIPEndPoint(session_->connection()->peer_address())}, - /*aliases=*/{}, use_dns_aliases_)) { - LogConnectionIpPooling(true); - session_->connection()->CloseConnection( - quic::QUIC_CONNECTION_IP_POOLED, - "An active session exists for the given IP.", - quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); - session_ = nullptr; - return OK; - } - LogConnectionIpPooling(false); - - std::set dns_aliases = - use_dns_aliases_ && resolve_host_request_->GetDnsAliasResults() - ? *resolve_host_request_->GetDnsAliasResults() - : std::set(); - pool_->ActivateSession(key_, session_, std::move(dns_aliases)); - - return OK; -} - QuicSessionRequest::QuicSessionRequest(QuicSessionPool* pool) : pool_(pool) {} QuicSessionRequest::~QuicSessionRequest() { @@ -942,12 +167,14 @@ QuicSessionRequest::~QuicSessionRequest() { int QuicSessionRequest::Request( url::SchemeHostPort destination, quic::ParsedQuicVersion quic_version, + const ProxyChain& proxy_chain, + const std::optional proxy_annotation_tag, + SessionUsage session_usage, PrivacyMode privacy_mode, RequestPriority priority, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, - bool use_dns_aliases, bool require_dns_https_alpn, int cert_verify_flags, const GURL& url, @@ -965,13 +192,16 @@ int QuicSessionRequest::Request( failed_on_default_network_callback_ = std::move(failed_on_default_network_callback); - session_key_ = QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, - socket_tag, network_anonymization_key, - secure_dns_policy, require_dns_https_alpn); + session_key_ = + QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, proxy_chain, + session_usage, socket_tag, network_anonymization_key, + secure_dns_policy, require_dns_https_alpn); + bool use_dns_aliases = session_usage == SessionUsage::kProxy ? false : true; int rv = pool_->RequestSession(session_key_, std::move(destination), - quic_version, priority, use_dns_aliases, - cert_verify_flags, url, net_log, this); + quic_version, std::move(proxy_annotation_tag), + priority, use_dns_aliases, cert_verify_flags, + url, net_log, this); if (rv == ERR_IO_PENDING) { net_log_ = net_log; callback_ = std::move(callback); @@ -1068,16 +298,18 @@ void QuicSessionRequest::SetSession( bool QuicSessionRequest::CanUseExistingSession( const GURL& url, + const ProxyChain& proxy_chain, PrivacyMode privacy_mode, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, bool require_dns_https_alpn, const url::SchemeHostPort& destination) const { return pool_->CanUseExistingSession( - QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag, - network_anonymization_key, secure_dns_policy, - require_dns_https_alpn), + QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, proxy_chain, + session_usage, socket_tag, network_anonymization_key, + secure_dns_policy, require_dns_https_alpn), destination); } @@ -1099,6 +331,74 @@ bool QuicSessionPool::QuicSessionAliasKey::operator==( session_key_ == other.session_key_; } +QuicSessionPool::QuicCryptoClientConfigOwner::QuicCryptoClientConfigOwner( + std::unique_ptr proof_verifier, + std::unique_ptr session_cache, + QuicSessionPool* quic_session_pool) + : config_(std::move(proof_verifier), std::move(session_cache)), + clock_(base::DefaultClock::GetInstance()), + quic_session_pool_(quic_session_pool) { + DCHECK(quic_session_pool_); + memory_pressure_listener_ = std::make_unique( + FROM_HERE, + base::BindRepeating(&QuicCryptoClientConfigOwner::OnMemoryPressure, + base::Unretained(this))); + if (quic_session_pool_->ssl_config_service_->GetSSLContextConfig() + .PostQuantumKeyAgreementEnabled()) { + config_.set_preferred_groups({SSL_GROUP_X25519_KYBER768_DRAFT00, + SSL_GROUP_X25519, SSL_GROUP_SECP256R1, + SSL_GROUP_SECP384R1}); + } +} +QuicSessionPool::QuicCryptoClientConfigOwner::~QuicCryptoClientConfigOwner() { + DCHECK_EQ(num_refs_, 0); +} + +void QuicSessionPool::QuicCryptoClientConfigOwner::OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { + quic::SessionCache* session_cache = config_.session_cache(); + if (!session_cache) { + return; + } + time_t now = clock_->Now().ToTimeT(); + uint64_t now_u64 = 0; + if (now > 0) { + now_u64 = static_cast(now); + } + switch (memory_pressure_level) { + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: + break; + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: + session_cache->RemoveExpiredEntries( + quic::QuicWallTime::FromUNIXSeconds(now_u64)); + break; + case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: + session_cache->Clear(); + break; + } +} + +QuicSessionPool::CryptoClientConfigHandle::CryptoClientConfigHandle( + const QuicCryptoClientConfigMap::iterator& map_iterator) + : map_iterator_(map_iterator) { + DCHECK_GE(map_iterator_->second->num_refs(), 0); + map_iterator->second->AddRef(); +} + +QuicSessionPool::CryptoClientConfigHandle::~CryptoClientConfigHandle() { + DCHECK_GT(map_iterator_->second->num_refs(), 0); + map_iterator_->second->ReleaseRef(); + if (map_iterator_->second->num_refs() == 0) { + map_iterator_->second->quic_session_pool()->OnAllCryptoClientRefReleased( + map_iterator_); + } +} + +quic::QuicCryptoClientConfig* +QuicSessionPool::CryptoClientConfigHandle::GetConfig() const { + return map_iterator_->second->config(); +} + QuicSessionPool::QuicSessionPool( NetLog* net_log, HostResolver* host_resolver, @@ -1200,15 +500,17 @@ bool QuicSessionPool::CanUseExistingSession( return false; } -int QuicSessionPool::RequestSession(const QuicSessionKey& session_key, - url::SchemeHostPort destination, - quic::ParsedQuicVersion quic_version, - RequestPriority priority, - bool use_dns_aliases, - int cert_verify_flags, - const GURL& url, - const NetLogWithSource& net_log, - QuicSessionRequest* request) { +int QuicSessionPool::RequestSession( + const QuicSessionKey& session_key, + url::SchemeHostPort destination, + quic::ParsedQuicVersion quic_version, + const std::optional proxy_annotation_tag, + RequestPriority priority, + bool use_dns_aliases, + int cert_verify_flags, + const GURL& url, + const NetLogWithSource& net_log, + QuicSessionRequest* request) { if (clock_skew_detector_.ClockSkewDetected(base::TimeTicks::Now(), base::Time::Now())) { MarkAllActiveSessionsGoingAway(kClockSkewDetected); @@ -1261,8 +563,13 @@ int QuicSessionPool::RequestSession(const QuicSessionKey& session_key, tick_clock_ = base::DefaultTickClock::GetInstance(); } + // If a proxy is in use, then a traffic annotation is required. + if (!session_key.proxy_chain().is_direct()) { + DCHECK(proxy_annotation_tag); + } + QuicSessionAliasKey key(destination, session_key); - std::unique_ptr job = std::make_unique( + std::unique_ptr job = std::make_unique( this, quic_version, host_resolver_, key, CreateCryptoConfigHandle(session_key.network_anonymization_key()), WasQuicRecentlyBroken(session_key), @@ -1461,7 +768,7 @@ void QuicSessionPool::FinishConnectAndConfigureSocket( } if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) { - rv = socket->SetRecvEcn(); + rv = socket->SetRecvTos(); if (rv != OK) { OnFinishConnectAndConfigureSocketError( std::move(callback), CREATION_ERROR_SETTING_RECEIVE_ECN, rv); @@ -1554,7 +861,7 @@ int QuicSessionPool::ConfigureSocket(DatagramClientSocket* socket, } if (base::FeatureList::IsEnabled(net::features::kReceiveEcn)) { - rv = socket->SetRecvEcn(); + rv = socket->SetRecvTos(); if (rv != OK) { HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_ECN); return rv; @@ -1846,13 +1153,13 @@ void QuicSessionPool::OnJobComplete(Job* job, int rv) { auto session_it = active_sessions_.find(job->key().session_key()); CHECK(session_it != active_sessions_.end()); QuicChromiumClientSession* session = session_it->second; - for (auto* request : iter->second->stream_requests()) { + for (QuicSessionRequest* request : iter->second->requests()) { // Do not notify |request| yet. request->SetSession(session->CreateHandle(job->key().destination())); } } - for (auto* request : iter->second->stream_requests()) { + for (QuicSessionRequest* request : iter->second->requests()) { // Even though we're invoking callbacks here, we don't need to worry // about |this| being deleted, because the pool is owned by the // profile which can not be deleted via callbacks. @@ -2394,8 +1701,8 @@ QuicSessionPool::CreateCryptoConfigHandle( DCHECK_EQ(mru_iterator->second->num_refs(), 0); map_iterator = active_crypto_config_map_ - .emplace(std::make_pair(actual_network_anonymization_key, - std::move(mru_iterator->second))) + .emplace(actual_network_anonymization_key, + std::move(mru_iterator->second)) .first; recent_crypto_config_map_.Erase(mru_iterator); return std::make_unique(map_iterator); @@ -2429,8 +1736,8 @@ QuicSessionPool::CreateCryptoConfigHandle( } map_iterator = active_crypto_config_map_ - .emplace(std::make_pair(actual_network_anonymization_key, - std::move(crypto_config_owner))) + .emplace(actual_network_anonymization_key, + std::move(crypto_config_owner)) .first; return std::make_unique(map_iterator); } diff --git a/naiveproxy/src/net/quic/quic_session_pool.h b/naiveproxy/src/net/quic/quic_session_pool.h index 672c1206a0..7ef8c3657b 100644 --- a/naiveproxy/src/net/quic/quic_session_pool.h +++ b/naiveproxy/src/net/quic/quic_session_pool.h @@ -16,10 +16,13 @@ #include "base/containers/lru_cache.h" #include "base/gtest_prod_util.h" +#include "base/memory/memory_pressure_monitor.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/task/sequenced_task_runner.h" +#include "base/time/default_clock.h" +#include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "net/base/address_list.h" @@ -30,6 +33,7 @@ #include "net/base/network_change_notifier.h" #include "net/base/network_handle.h" #include "net/base/proxy_server.h" +#include "net/base/session_usage.h" #include "net/cert/cert_database.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_server_properties.h" @@ -44,6 +48,7 @@ #include "net/quic/quic_session_key.h" #include "net/socket/client_socket_pool.h" #include "net/ssl/ssl_config_service.h" +#include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_client_session_cache.h" #include "net/third_party/quiche/src/quiche/quic/core/deterministic_connection_id_generator.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_config.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h" @@ -74,6 +79,7 @@ struct HostResolverEndpointResult; class HttpServerProperties; class NetLog; class NetworkAnonymizationKey; +struct NetworkTrafficAnnotationTag; class QuicChromiumConnectionHelper; class QuicCryptoClientStreamFactory; class QuicServerInfo; @@ -134,29 +140,31 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { ~QuicSessionRequest(); - // |cert_verify_flags| is bitwise OR'd of CertVerifier::VerifyFlags and it is + // `cert_verify_flags` is bitwise OR'd of CertVerifier::VerifyFlags and it is // passed to CertVerifier::Verify. - // |destination| will be resolved and resulting IPEndPoint used to open a + // `destination` will be resolved and resulting IPEndPoint used to open a // quic::QuicConnection. This can be different than // HostPortPair::FromURL(url). - // When |use_dns_aliases| is true, any DNS aliases found in host resolution - // are stored in the |dns_aliases_by_session_key_| map. |use_dns_aliases| - // should be false in the case of a proxy. - int Request(url::SchemeHostPort destination, - quic::ParsedQuicVersion quic_version, - PrivacyMode privacy_mode, - RequestPriority priority, - const SocketTag& socket_tag, - const NetworkAnonymizationKey& network_anonymization_key, - SecureDnsPolicy secure_dns_policy, - bool use_dns_aliases, - bool require_dns_https_alpn, - int cert_verify_flags, - const GURL& url, - const NetLogWithSource& net_log, - NetErrorDetails* net_error_details, - CompletionOnceCallback failed_on_default_network_callback, - CompletionOnceCallback callback); + // When `session_usage` is `kDestination`, any DNS aliases found in host + // resolution are stored in the `dns_aliases_by_session_key_` map. + int Request( + url::SchemeHostPort destination, + quic::ParsedQuicVersion quic_version, + const ProxyChain& proxy_chain, + const std::optional proxy_annotation_tag, + SessionUsage session_usage, + PrivacyMode privacy_mode, + RequestPriority priority, + const SocketTag& socket_tag, + const NetworkAnonymizationKey& network_anonymization_key, + SecureDnsPolicy secure_dns_policy, + bool require_dns_https_alpn, + int cert_verify_flags, + const GURL& url, + const NetLogWithSource& net_log, + NetErrorDetails* net_error_details, + CompletionOnceCallback failed_on_default_network_callback, + CompletionOnceCallback callback); // This function must be called after Request() returns ERR_IO_PENDING. // Returns true if Request() requires host resolution and it hasn't completed @@ -167,14 +175,6 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { // ERR_IO_PENDING. bool WaitForHostResolution(CompletionOnceCallback callback); - // Tells QuicSessionRequest it should expect OnHostResolutionComplete() - // to be called in the future. - void ExpectOnHostResolution(); - - // Will be called by the associated QuicSessionPool::Job when host - // resolution completes asynchronously after Request(). - void OnHostResolutionComplete(int rv); - // This function must be called after Request() returns ERR_IO_PENDING. // Returns true if no QUIC session has been created yet. If true is returned, // `callback` will be run when the QUIC session has been created and will be @@ -183,12 +183,31 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { // `callback` will be run with ERR_IO_PENDING. bool WaitForQuicSessionCreation(CompletionOnceCallback callback); - // Tells QuicSessionRequest it should expect OnQuicSessionCreationComplete() - // to be called in the future. + // QuicSessionPool::Jobs may notify associated requests at two points in the + // connection process before completion: host resolution and session creation. + // The `Expect` methods below inform the request whether it should expect + // these notifications. + + // Tells QuicSessionRequest that `QuicSessionPool::Job` will call + // `OnHostResolutionComplete()` in the future. Must be called before + // `WaitForHostResolution()` + void ExpectOnHostResolution(); + + // Will be called by the associated `QuicSessionPool::Job` when host + // resolution completes asynchronously after Request(), if + // `ExpectOnHostResolution()` was called. This is called after the Job can + // make no further progress, and includes the result of that progress, perhaps + // `ERR_IO_PENDING`. + void OnHostResolutionComplete(int rv); + + // Tells QuicSessionRequest that `QuicSessionPool::Job` will call + // `OnQuicSessionCreationComplete()` in the future. Must be called before + // `WaitForQuicSessionCreation()`. void ExpectQuicSessionCreation(); - // Will be called by the associated QuicSessionPool::Job when session - // creation completes asynchronously after Request(). + // Will be called by the associated `QuicSessionPool::Job` when session + // creation completes asynchronously after Request(), if + // `ExpectQuicSessionCreation` was called. void OnQuicSessionCreationComplete(int rv); void OnRequestComplete(int rv); @@ -220,7 +239,9 @@ class NET_EXPORT_PRIVATE QuicSessionRequest { bool CanUseExistingSession( const GURL& url, + const ProxyChain& proxy_chain, PrivacyMode privacy_mode, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -277,8 +298,6 @@ class NET_EXPORT_PRIVATE QuicSessionPool } const QuicSessionKey& session_key() const { return session_key_; } - // Returns the estimate of dynamically allocated memory in bytes. - private: url::SchemeHostPort destination_; QuicSessionKey session_key_; @@ -316,15 +335,19 @@ class NET_EXPORT_PRIVATE QuicSessionPool // When |use_dns_aliases| is true, any DNS aliases found in host resolution // are stored in the |dns_aliases_by_session_key_| map. |use_dns_aliases| // should be false in the case of a proxy. - int RequestSession(const QuicSessionKey& session_key, - url::SchemeHostPort destination, - quic::ParsedQuicVersion quic_version, - RequestPriority priority, - bool use_dns_aliases, - int cert_verify_flags, - const GURL& url, - const NetLogWithSource& net_log, - QuicSessionRequest* request); + // When the `proxy_chain` in the session key is not direct, + // `proxy_annotation_tag` must be set. + int RequestSession( + const QuicSessionKey& session_key, + url::SchemeHostPort destination, + quic::ParsedQuicVersion quic_version, + const std::optional proxy_annotation_tag, + RequestPriority priority, + bool use_dns_aliases, + int cert_verify_flags, + const GURL& url, + const NetLogWithSource& net_log, + QuicSessionRequest* request); // Called by a session when it is going away and no more streams should be // created on it. @@ -453,6 +476,7 @@ class NET_EXPORT_PRIVATE QuicSessionPool private: class Job; + class DirectJob; class QuicCryptoClientConfigOwner; class CryptoClientConfigHandle; friend class MockQuicSessionPool; @@ -463,7 +487,8 @@ class NET_EXPORT_PRIVATE QuicSessionPool std::map; using AliasSet = std::set; using SessionAliasMap = std::map; - using SessionSet = std::set; + using SessionSet = + std::set>; using IPAliasMap = std::map; using SessionPeerIPMap = std::map; using JobMap = std::map>; @@ -525,9 +550,12 @@ class NET_EXPORT_PRIVATE QuicSessionPool raw_ptr* session, handles::NetworkHandle* network, std::unique_ptr socket); + + // Called when the Job for the given key has created and confirmed a session. void ActivateSession(const QuicSessionAliasKey& key, QuicChromiumClientSession* session, std::set dns_aliases); + // Go away all active sessions. May disable session's connectivity monitoring // based on the |reason|. void MarkAllActiveSessionsGoingAway(AllActiveSessionsGoingAwayReason reason); @@ -737,6 +765,76 @@ class NET_EXPORT_PRIVATE QuicSessionPool base::WeakPtrFactory weak_factory_{this}; }; +// Refcounted class that owns quic::QuicCryptoClientConfig and tracks how many +// consumers are using it currently. When the last reference is freed, the +// QuicCryptoClientConfigHandle informs the owning QuicSessionPool, moves it +// into an MRU cache. +class QuicSessionPool::QuicCryptoClientConfigOwner { + public: + QuicCryptoClientConfigOwner( + std::unique_ptr proof_verifier, + std::unique_ptr session_cache, + QuicSessionPool* quic_session_pool); + + QuicCryptoClientConfigOwner(const QuicCryptoClientConfigOwner&) = delete; + QuicCryptoClientConfigOwner& operator=(const QuicCryptoClientConfigOwner&) = + delete; + + ~QuicCryptoClientConfigOwner(); + + quic::QuicCryptoClientConfig* config() { return &config_; } + + int num_refs() const { return num_refs_; } + + QuicSessionPool* quic_session_pool() { return quic_session_pool_; } + + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); + + private: + friend class CryptoClientConfigHandle; + + // Simple ref counting. Not using scoped_refptr allows for both keeping around + // an MRU cache of 0-reference objects, and DCHECKing that there are no + // outstanding referenced QuicCryptoClientConfigOwner on destruction. Private + // so that only CryptoClientConfigHandle can add and remove refs. + + void AddRef() { num_refs_++; } + + void ReleaseRef() { + DCHECK_GT(num_refs_, 0); + num_refs_--; + } + + int num_refs_ = 0; + quic::QuicCryptoClientConfig config_; + raw_ptr clock_; + std::unique_ptr memory_pressure_listener_; + const raw_ptr quic_session_pool_; +}; + +// Class that owns a reference to a QuicCryptoClientConfigOwner. Handles +// incrementing the refcount on construction, and decrementing it on +// destruction. +class QuicSessionPool::CryptoClientConfigHandle + : public QuicCryptoClientConfigHandle { + public: + explicit CryptoClientConfigHandle( + const QuicCryptoClientConfigMap::iterator& map_iterator); + + CryptoClientConfigHandle(const CryptoClientConfigHandle& other) + : CryptoClientConfigHandle(other.map_iterator_) {} + + CryptoClientConfigHandle& operator=(const CryptoClientConfigHandle&) = delete; + + ~CryptoClientConfigHandle() override; + + quic::QuicCryptoClientConfig* GetConfig() const override; + + private: + QuicCryptoClientConfigMap::iterator map_iterator_; +}; + } // namespace net #endif // NET_QUIC_QUIC_SESSION_POOL_H_ diff --git a/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc b/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc new file mode 100644 index 0000000000..26cd9e2dcf --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_pool_direct_job.cc @@ -0,0 +1,520 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/quic_session_pool_direct_job.h" + +#include "base/memory/weak_ptr.h" +#include "net/base/completion_once_callback.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_handle.h" +#include "net/base/request_priority.h" +#include "net/base/trace_constants.h" +#include "net/base/tracing.h" +#include "net/dns/host_resolver.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/address_utils.h" +#include "net/quic/quic_crypto_client_config_handle.h" +#include "net/quic/quic_http_stream.h" +#include "net/quic/quic_session_pool.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" + +namespace net { + +namespace { + +enum class JobProtocolErrorLocation { + kSessionStartReadingFailedAsync = 0, + kSessionStartReadingFailedSync = 1, + kCreateSessionFailedAsync = 2, + kCreateSessionFailedSync = 3, + kCryptoConnectFailedSync = 4, + kCryptoConnectFailedAsync = 5, + kMaxValue = kCryptoConnectFailedAsync, +}; + +void HistogramProtocolErrorLocation(enum JobProtocolErrorLocation location) { + UMA_HISTOGRAM_ENUMERATION("Net.QuicStreamFactory.DoConnectFailureLocation", + location); +} + +void LogConnectionIpPooling(bool pooled) { + UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectionIpPooled", pooled); +} + +void LogStaleConnectionTime(base::TimeTicks start_time) { + UMA_HISTOGRAM_TIMES("Net.QuicSession.StaleConnectionTime", + base::TimeTicks::Now() - start_time); +} + +void LogValidConnectionTime(base::TimeTicks start_time) { + UMA_HISTOGRAM_TIMES("Net.QuicSession.ValidConnectionTime", + base::TimeTicks::Now() - start_time); +} + +} // namespace + +QuicSessionPool::DirectJob::DirectJob( + QuicSessionPool* pool, + quic::ParsedQuicVersion quic_version, + HostResolver* host_resolver, + const QuicSessionAliasKey& key, + std::unique_ptr client_config_handle, + bool was_alternative_service_recently_broken, + bool retry_on_alternate_network_before_handshake, + RequestPriority priority, + bool use_dns_aliases, + bool require_dns_https_alpn, + int cert_verify_flags, + const NetLogWithSource& net_log) + : QuicSessionPool::Job::Job(pool, + key, + std::move(client_config_handle), + priority, + net_log), + quic_version_(quic_version), + host_resolver_(host_resolver), + use_dns_aliases_(use_dns_aliases), + require_dns_https_alpn_(require_dns_https_alpn), + cert_verify_flags_(cert_verify_flags), + was_alternative_service_recently_broken_( + was_alternative_service_recently_broken), + retry_on_alternate_network_before_handshake_( + retry_on_alternate_network_before_handshake), + network_(handles::kInvalidNetworkHandle) { + DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn); +} + +QuicSessionPool::DirectJob::~DirectJob() {} + +int QuicSessionPool::DirectJob::Run(CompletionOnceCallback callback) { + int rv = DoLoop(OK); + if (rv == ERR_IO_PENDING) { + callback_ = std::move(callback); + } + + return rv > 0 ? OK : rv; +} + +void QuicSessionPool::DirectJob::SetRequestExpectations( + QuicSessionRequest* request) { + if (!host_resolution_finished_) { + request->ExpectOnHostResolution(); + } + // Callers do not need to wait for OnQuicSessionCreationComplete if the + // kAsyncQuicSession flag is not set because session creation will be fully + // synchronous, so no need to call ExpectQuicSessionCreation. + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession) && + !session_creation_finished_) { + request->ExpectQuicSessionCreation(); + } +} + +void QuicSessionPool::DirectJob::UpdatePriority(RequestPriority old_priority, + RequestPriority new_priority) { + if (old_priority == new_priority) { + return; + } + + if (resolve_host_request_ && !host_resolution_finished_) { + resolve_host_request_->ChangeRequestPriority(new_priority); + } +} + +void QuicSessionPool::DirectJob::PopulateNetErrorDetails( + NetErrorDetails* details) const { + if (!session_) { + return; + } + details->connection_info = QuicHttpStream::ConnectionInfoFromQuicVersion( + session_->connection()->version()); + details->quic_connection_error = session_->error(); +} + +int QuicSessionPool::DirectJob::DoLoop(int rv) { + TRACE_EVENT0(NetTracingCategory(), "QuicSessionPool::DirectJob::DoLoop"); + + do { + IoState state = io_state_; + io_state_ = STATE_NONE; + switch (state) { + case STATE_RESOLVE_HOST: + CHECK_EQ(OK, rv); + rv = DoResolveHost(); + break; + case STATE_RESOLVE_HOST_COMPLETE: + rv = DoResolveHostComplete(rv); + break; + case STATE_CREATE_SESSION: + rv = DoCreateSession(); + break; + case STATE_CREATE_SESSION_COMPLETE: + rv = DoCreateSessionComplete(rv); + break; + case STATE_CONNECT: + rv = DoConnect(rv); + break; + case STATE_CONFIRM_CONNECTION: + rv = DoConfirmConnection(rv); + break; + default: + NOTREACHED() << "io_state_: " << io_state_; + break; + } + } while (io_state_ != STATE_NONE && rv != ERR_IO_PENDING); + return rv; +} + +int QuicSessionPool::DirectJob::DoResolveHost() { + dns_resolution_start_time_ = base::TimeTicks::Now(); + + io_state_ = STATE_RESOLVE_HOST_COMPLETE; + + HostResolver::ResolveHostParameters parameters; + parameters.initial_priority = priority_; + parameters.secure_dns_policy = key_.session_key().secure_dns_policy(); + resolve_host_request_ = host_resolver_->CreateRequest( + key_.destination(), key_.session_key().network_anonymization_key(), + net_log_, parameters); + // Unretained is safe because |this| owns the request, ensuring cancellation + // on destruction. + return resolve_host_request_->Start( + base::BindOnce(&QuicSessionPool::DirectJob::OnResolveHostComplete, + base::Unretained(this))); +} + +int QuicSessionPool::DirectJob::DoResolveHostComplete(int rv) { + host_resolution_finished_ = true; + dns_resolution_end_time_ = base::TimeTicks::Now(); + if (rv != OK) { + return rv; + } + + DCHECK(!pool_->HasActiveSession(key_.session_key())); + + // Inform the pool of this resolution, which will set up + // a session alias, if possible. + const bool svcb_optional = + IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); + for (const auto& endpoint : *resolve_host_request_->GetEndpointResults()) { + // Only consider endpoints that would have been eligible for QUIC. + if (!SelectQuicVersion(endpoint, svcb_optional).IsKnown()) { + continue; + } + if (pool_->HasMatchingIpSession( + key_, endpoint.ip_endpoints, + *resolve_host_request_->GetDnsAliasResults(), use_dns_aliases_)) { + LogConnectionIpPooling(true); + return OK; + } + } + io_state_ = STATE_CREATE_SESSION; + return OK; +} + +int QuicSessionPool::DirectJob::DoCreateSession() { + // TODO(https://crbug.com/1416409): This logic only knows how to try one + // endpoint result. + bool svcb_optional = + IsSvcbOptional(*resolve_host_request_->GetEndpointResults()); + bool found = false; + for (const auto& candidate : *resolve_host_request_->GetEndpointResults()) { + quic::ParsedQuicVersion version = + SelectQuicVersion(candidate, svcb_optional); + if (version.IsKnown()) { + found = true; + quic_version_used_ = version; + endpoint_result_ = candidate; + break; + } + } + if (!found) { + return ERR_DNS_NO_MATCHING_SUPPORTED_ALPN; + } + + quic_connection_start_time_ = base::TimeTicks::Now(); + DCHECK(dns_resolution_end_time_ != base::TimeTicks()); + io_state_ = STATE_CREATE_SESSION_COMPLETE; + bool require_confirmation = was_alternative_service_recently_broken_; + net_log_.AddEntryWithBoolParams( + NetLogEventType::QUIC_SESSION_POOL_JOB_CONNECT, NetLogEventPhase::BEGIN, + "require_confirmation", require_confirmation); + + DCHECK_NE(quic_version_used_, quic::ParsedQuicVersion::Unsupported()); + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { + return pool_->CreateSessionAsync( + base::BindOnce(&QuicSessionPool::DirectJob::OnCreateSessionComplete, + GetWeakPtr()), + key_, quic_version_used_, cert_verify_flags_, require_confirmation, + endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, + net_log_, &session_, &network_); + } + int rv = pool_->CreateSessionSync( + key_, quic_version_used_, cert_verify_flags_, require_confirmation, + endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, + net_log_, &session_, &network_); + + DVLOG(1) << "Created session on network: " << network_; + + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + DCHECK(!session_); + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCreateSessionFailedSync); + } + + return rv; +} + +int QuicSessionPool::DirectJob::DoCreateSessionComplete(int rv) { + session_creation_finished_ = true; + if (rv != OK) { + return rv; + } + io_state_ = STATE_CONNECT; + if (!session_->connection()->connected()) { + return ERR_CONNECTION_CLOSED; + } + + session_->StartReading(); + if (!session_->connection()->connected()) { + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kSessionStartReadingFailedAsync); + } else { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kSessionStartReadingFailedSync); + } + return ERR_QUIC_PROTOCOL_ERROR; + } + return OK; +} + +int QuicSessionPool::DirectJob::DoConnect(int rv) { + if (rv != OK) { + return rv; + } + DCHECK(session_); + io_state_ = STATE_CONFIRM_CONNECTION; + rv = session_->CryptoConnect(base::BindOnce( + &QuicSessionPool::DirectJob::OnCryptoConnectComplete, GetWeakPtr())); + + if (rv != ERR_IO_PENDING) { + LogValidConnectionTime(quic_connection_start_time_); + } + + if (!session_->connection()->connected() && + session_->error() == quic::QUIC_PROOF_INVALID) { + return ERR_QUIC_HANDSHAKE_FAILED; + } + + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCryptoConnectFailedSync); + } + + return rv; +} + +int QuicSessionPool::DirectJob::DoConfirmConnection(int rv) { + UMA_HISTOGRAM_TIMES("Net.QuicSession.TimeFromResolveHostToConfirmConnection", + base::TimeTicks::Now() - dns_resolution_start_time_); + net_log_.EndEvent(NetLogEventType::QUIC_SESSION_POOL_JOB_CONNECT); + + if (was_alternative_service_recently_broken_) { + UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ConnectAfterBroken", rv == OK); + } + + if (retry_on_alternate_network_before_handshake_ && session_ && + !session_->OneRttKeysAvailable() && + network_ == pool_->default_network()) { + if (session_->error() == quic::QUIC_NETWORK_IDLE_TIMEOUT || + session_->error() == quic::QUIC_HANDSHAKE_TIMEOUT || + session_->error() == quic::QUIC_PACKET_WRITE_ERROR) { + // Retry the connection on an alternate network if crypto handshake failed + // with network idle time out or handshake time out. + DCHECK(network_ != handles::kInvalidNetworkHandle); + network_ = pool_->FindAlternateNetwork(network_); + connection_retried_ = network_ != handles::kInvalidNetworkHandle; + UMA_HISTOGRAM_BOOLEAN( + "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake", + connection_retried_); + UMA_HISTOGRAM_ENUMERATION( + "Net.QuicStreamFactory.AttemptMigrationBeforeHandshake." + "FailedConnectionType", + NetworkChangeNotifier::GetNetworkConnectionType( + pool_->default_network()), + NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1); + if (connection_retried_) { + UMA_HISTOGRAM_ENUMERATION( + "Net.QuicStreamFactory.MigrationBeforeHandshake.NewConnectionType", + NetworkChangeNotifier::GetNetworkConnectionType(network_), + NetworkChangeNotifier::ConnectionType::CONNECTION_LAST + 1); + net_log_.AddEvent( + NetLogEventType::QUIC_SESSION_POOL_JOB_RETRY_ON_ALTERNATE_NETWORK); + // Notify requests that connection on the default network failed. + for (QuicSessionRequest* request : requests()) { + request->OnConnectionFailedOnDefaultNetwork(); + } + DVLOG(1) << "Retry connection on alternate network: " << network_; + session_ = nullptr; + io_state_ = STATE_CREATE_SESSION; + return OK; + } + } + } + + if (connection_retried_) { + UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.MigrationBeforeHandshake2", + rv == OK); + if (rv == OK) { + UMA_HISTOGRAM_BOOLEAN( + "Net.QuicStreamFactory.NetworkChangeDuringMigrationBeforeHandshake", + network_ == pool_->default_network()); + } else { + base::UmaHistogramSparse( + "Net.QuicStreamFactory.MigrationBeforeHandshakeFailedReason", -rv); + } + } else if (network_ != handles::kInvalidNetworkHandle && + network_ != pool_->default_network()) { + UMA_HISTOGRAM_BOOLEAN("Net.QuicStreamFactory.ConnectionOnNonDefaultNetwork", + rv == OK); + } + + if (rv != OK) { + return rv; + } + + DCHECK(!pool_->HasActiveSession(key_.session_key())); + // There may well now be an active session for this IP. If so, use the + // existing session instead. + if (pool_->HasMatchingIpSession( + key_, {ToIPEndPoint(session_->connection()->peer_address())}, + /*aliases=*/{}, use_dns_aliases_)) { + LogConnectionIpPooling(true); + session_->connection()->CloseConnection( + quic::QUIC_CONNECTION_IP_POOLED, + "An active session exists for the given IP.", + quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); + session_ = nullptr; + return OK; + } + LogConnectionIpPooling(false); + + std::set dns_aliases = + use_dns_aliases_ && resolve_host_request_->GetDnsAliasResults() + ? *resolve_host_request_->GetDnsAliasResults() + : std::set(); + pool_->ActivateSession(key_, session_, std::move(dns_aliases)); + + return OK; +} + +void QuicSessionPool::DirectJob::OnResolveHostComplete(int rv) { + DCHECK(!host_resolution_finished_); + io_state_ = STATE_RESOLVE_HOST_COMPLETE; + rv = DoLoop(rv); + + for (QuicSessionRequest* request : requests()) { + request->OnHostResolutionComplete(rv); + } + + if (rv != ERR_IO_PENDING && !callback_.is_null()) { + std::move(callback_).Run(rv); + } +} + +void QuicSessionPool::DirectJob::OnCreateSessionComplete(int rv) { + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCreateSessionFailedAsync); + } + if (rv == OK) { + DCHECK(session_); + DVLOG(1) << "Created session on network: " << network_; + } + + rv = DoLoop(rv); + + for (QuicSessionRequest* request : requests()) { + request->OnQuicSessionCreationComplete(rv); + } + + if (rv != ERR_IO_PENDING && !callback_.is_null()) { + std::move(callback_).Run(rv); + } +} + +void QuicSessionPool::DirectJob::OnCryptoConnectComplete(int rv) { + // This early return will be triggered when CloseSessionOnError is called + // before crypto handshake has completed. + if (!session_) { + LogStaleConnectionTime(quic_connection_start_time_); + return; + } + + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCryptoConnectFailedAsync); + } + + io_state_ = STATE_CONFIRM_CONNECTION; + rv = DoLoop(rv); + if (rv != ERR_IO_PENDING && !callback_.is_null()) { + std::move(callback_).Run(rv); + } +} + +bool QuicSessionPool::DirectJob::IsSvcbOptional( + base::span results) const { + // If SVCB/HTTPS resolution succeeded, the client supports ECH, and all + // routes support ECH, disable the A/AAAA fallback. See Section 10.1 of + // draft-ietf-dnsop-svcb-https-11. + if (!pool_->ssl_config_service_->GetSSLContextConfig().ech_enabled) { + return true; // ECH is not supported for this request. + } + + return !HostResolver::AllProtocolEndpointsHaveEch(results); +} + +quic::ParsedQuicVersion QuicSessionPool::DirectJob::SelectQuicVersion( + const HostResolverEndpointResult& endpoint_result, + bool svcb_optional) const { + // TODO(davidben): `require_dns_https_alpn_` only exists to be `DCHECK`ed + // for consistency against `quic_version_`. Remove the parameter? + DCHECK_EQ(require_dns_https_alpn_, !quic_version_.IsKnown()); + + if (endpoint_result.metadata.supported_protocol_alpns.empty()) { + // `endpoint_result` came from A/AAAA records directly, without HTTPS/SVCB + // records. If we know the QUIC ALPN to use externally, i.e. via Alt-Svc, + // use it in SVCB-optional mode. Otherwise, `endpoint_result` is not + // eligible for QUIC. + return svcb_optional ? quic_version_ + : quic::ParsedQuicVersion::Unsupported(); + } + + // Otherwise, `endpoint_result` came from an HTTPS/SVCB record. We can use + // QUIC if a suitable match is found in the record's ALPN list. + // Additionally, if this connection attempt came from Alt-Svc, the DNS + // result must be consistent with it. See + // https://www.ietf.org/archive/id/draft-ietf-dnsop-svcb-https-11.html#name-interaction-with-alt-svc + if (quic_version_.IsKnown()) { + std::string expected_alpn = quic::AlpnForVersion(quic_version_); + if (base::Contains(endpoint_result.metadata.supported_protocol_alpns, + quic::AlpnForVersion(quic_version_))) { + return quic_version_; + } + return quic::ParsedQuicVersion::Unsupported(); + } + + for (const auto& alpn : endpoint_result.metadata.supported_protocol_alpns) { + for (const auto& supported_version : pool_->supported_versions()) { + if (alpn == AlpnForVersion(supported_version)) { + return supported_version; + } + } + } + + return quic::ParsedQuicVersion::Unsupported(); +} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_pool_direct_job.h b/naiveproxy/src/net/quic/quic_session_pool_direct_job.h new file mode 100644 index 0000000000..f0b8b7597a --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_pool_direct_job.h @@ -0,0 +1,118 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_QUIC_SESSION_POOL_DIRECT_JOB_H_ +#define NET_QUIC_QUIC_SESSION_POOL_DIRECT_JOB_H_ + +#include "base/memory/weak_ptr.h" +#include "base/time/time.h" +#include "net/base/completion_once_callback.h" +#include "net/base/net_error_details.h" +#include "net/base/request_priority.h" +#include "net/dns/host_resolver.h" +#include "net/dns/public/host_resolver_results.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/quic_chromium_client_session.h" +#include "net/quic/quic_session_pool.h" +#include "net/quic/quic_session_pool_job.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" + +namespace net { + +// A DirectJob is a QuicSessionPool::Job that handles direct connections to the +// destination. +// +// A job works on behalf of a pool and a collection of requests to create a new +// QUIC session. +class QuicSessionPool::DirectJob : public QuicSessionPool::Job { + public: + DirectJob(QuicSessionPool* pool, + quic::ParsedQuicVersion quic_version, + HostResolver* host_resolver, + const QuicSessionAliasKey& key, + std::unique_ptr client_config_handle, + bool was_alternative_service_recently_broken, + bool retry_on_alternate_network_before_handshake, + RequestPriority priority, + bool use_dns_aliases, + bool require_dns_https_alpn, + int cert_verify_flags, + const NetLogWithSource& net_log); + + ~DirectJob() override; + + // QuicSessionPool::Job implementation. + int Run(CompletionOnceCallback callback) override; + void SetRequestExpectations(QuicSessionRequest* request) override; + void UpdatePriority(RequestPriority old_priority, + RequestPriority new_priority) override; + void PopulateNetErrorDetails(NetErrorDetails* details) const override; + + private: + int DoLoop(int rv); + int DoResolveHost(); + int DoResolveHostComplete(int rv); + int DoCreateSession(); + int DoCreateSessionComplete(int rv); + int DoConnect(int rv); + int DoConfirmConnection(int rv); + + void OnResolveHostComplete(int rv); + void OnCreateSessionComplete(int rv); + void OnCryptoConnectComplete(int rv); + + base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } + + enum IoState { + STATE_NONE, + STATE_RESOLVE_HOST, + STATE_RESOLVE_HOST_COMPLETE, + STATE_CREATE_SESSION, + STATE_CREATE_SESSION_COMPLETE, + STATE_CONNECT, + STATE_CONFIRM_CONNECTION, + }; + + // Returns whether the client should be SVCB-optional when connecting to + // `results`. + bool IsSvcbOptional( + base::span results) const; + + // Returns the QUIC version that would be used with `endpoint_result`, or + // `quic::ParsedQuicVersion::Unsupported()` if `endpoint_result` cannot be + // used with QUIC. + quic::ParsedQuicVersion SelectQuicVersion( + const HostResolverEndpointResult& endpoint_result, + bool svcb_optional) const; + + IoState io_state_ = STATE_RESOLVE_HOST; + quic::ParsedQuicVersion quic_version_; + quic::ParsedQuicVersion quic_version_used_ = + quic::ParsedQuicVersion::Unsupported(); + raw_ptr host_resolver_; + const bool use_dns_aliases_; + const bool require_dns_https_alpn_; + const int cert_verify_flags_; + const bool was_alternative_service_recently_broken_; + const bool retry_on_alternate_network_before_handshake_; + bool host_resolution_finished_ = false; + bool session_creation_finished_ = false; + bool connection_retried_ = false; + raw_ptr session_ = nullptr; + HostResolverEndpointResult endpoint_result_; + // If connection migraiton is supported, |network_| denotes the network on + // which |session_| is created. + handles::NetworkHandle network_; + CompletionOnceCallback host_resolution_callback_; + CompletionOnceCallback callback_; + std::unique_ptr resolve_host_request_; + base::TimeTicks dns_resolution_start_time_; + base::TimeTicks dns_resolution_end_time_; + base::TimeTicks quic_connection_start_time_; + base::WeakPtrFactory weak_factory_{this}; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_SESSION_POOL_DIRECT_JOB_H_ diff --git a/naiveproxy/src/net/quic/quic_session_pool_job.cc b/naiveproxy/src/net/quic/quic_session_pool_job.cc new file mode 100644 index 0000000000..23f71c7f54 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_pool_job.cc @@ -0,0 +1,86 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/quic/quic_session_pool_job.h" + +#include "base/memory/weak_ptr.h" +#include "net/base/completion_once_callback.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_handle.h" +#include "net/base/request_priority.h" +#include "net/base/trace_constants.h" +#include "net/base/tracing.h" +#include "net/dns/host_resolver.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/address_utils.h" +#include "net/quic/quic_crypto_client_config_handle.h" +#include "net/quic/quic_http_stream.h" +#include "net/quic/quic_session_pool.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" + +namespace net { + +namespace { + +base::Value::Dict NetLogQuicSessionPoolJobParams( + const QuicSessionPool::QuicSessionAliasKey* key) { + return base::Value::Dict() + .Set("host", key->server_id().host()) + .Set("port", key->server_id().port()) + .Set("privacy_mode", + PrivacyModeToDebugString(key->session_key().privacy_mode())) + .Set("network_anonymization_key", + key->session_key().network_anonymization_key().ToDebugString()); +} + +} // namespace + +QuicSessionPool::Job::Job( + QuicSessionPool* pool, + const QuicSessionAliasKey& key, + std::unique_ptr client_config_handle, + RequestPriority priority, + const NetLogWithSource& net_log) + : pool_(pool), + key_(key), + client_config_handle_(std::move(client_config_handle)), + priority_(priority), + net_log_( + NetLogWithSource::Make(net_log.net_log(), + NetLogSourceType::QUIC_SESSION_POOL_JOB)) { + net_log_.BeginEvent(NetLogEventType::QUIC_SESSION_POOL_JOB, + [&] { return NetLogQuicSessionPoolJobParams(&key_); }); + // Associate |net_log_| with |net_log|. + net_log_.AddEventReferencingSource( + NetLogEventType::QUIC_SESSION_POOL_JOB_BOUND_TO_HTTP_STREAM_JOB, + net_log.source()); + net_log.AddEventReferencingSource( + NetLogEventType::HTTP_STREAM_JOB_BOUND_TO_QUIC_SESSION_POOL_JOB, + net_log_.source()); +} + +QuicSessionPool::Job::~Job() { + net_log_.EndEvent(NetLogEventType::QUIC_SESSION_POOL_JOB); +} + +void QuicSessionPool::Job::AddRequest(QuicSessionRequest* request) { + requests_.insert(request); + SetRequestExpectations(request); +} + +void QuicSessionPool::Job::RemoveRequest(QuicSessionRequest* request) { + auto request_iter = requests_.find(request); + DCHECK(request_iter != requests_.end()); + requests_.erase(request_iter); +} + +void QuicSessionPool::Job::SetPriority(RequestPriority priority) { + UpdatePriority(priority_, priority); + priority_ = priority; +} + +void QuicSessionPool::Job::UpdatePriority(RequestPriority old_priority, + RequestPriority new_priority) {} + +} // namespace net diff --git a/naiveproxy/src/net/quic/quic_session_pool_job.h b/naiveproxy/src/net/quic/quic_session_pool_job.h new file mode 100644 index 0000000000..73cf6f1543 --- /dev/null +++ b/naiveproxy/src/net/quic/quic_session_pool_job.h @@ -0,0 +1,87 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_QUIC_QUIC_SESSION_POOL_JOB_H_ +#define NET_QUIC_QUIC_SESSION_POOL_JOB_H_ + +#include "base/memory/raw_ptr.h" +#include "net/base/net_error_details.h" +#include "net/base/request_priority.h" +#include "net/log/net_log_with_source.h" +#include "net/quic/quic_session_pool.h" + +namespace net { + +// Responsible for creating a new QUIC session to the specified server, and for +// notifying any associated requests when complete. +// +// A single Job can be associated with any number of `QuicSessionRequest` +// instances, and will update all of them with its progress, calling some or +// all of their `OnHostResolution()` or `OnQuicSessionCreationComplete()` +// methods, as indicated by calls to `ExpectOnHostResolution()` and +// `ExpectQuicSessionCreation()`, respectively. +// +// When the session is confirmed, the job will call the pool's +// `ActivateSession` method before invoking the callback from `Run`. +// +// The |client_config_handle| is not actually used, but serves to keep the +// corresponding CryptoClientConfig alive until the Job completes. +class QuicSessionPool::Job { + public: + Job(QuicSessionPool* pool, + const QuicSessionAliasKey& key, + std::unique_ptr client_config_handle, + RequestPriority priority, + const NetLogWithSource& net_log); + + Job(const Job&) = delete; + Job& operator=(const Job&) = delete; + + virtual ~Job(); + + // Run the job. This should be called as soon as the job is created, then any + // associated requests added with `AddRequest()`. + virtual int Run(CompletionOnceCallback callback) = 0; + + // Add a new request associated with this Job. + void AddRequest(QuicSessionRequest* request); + + // Remove a request associated with this job. The request must already be + // associated with the job. + void RemoveRequest(QuicSessionRequest* request); + + // Update the priority of this Job. + void SetPriority(RequestPriority priority); + + // Add information about the new session to `details`. Must be called after + // the run has completed. + virtual void PopulateNetErrorDetails(NetErrorDetails* details) const = 0; + + const QuicSessionAliasKey& key() const { return key_; } + const NetLogWithSource& net_log() const { return net_log_; } + const std::set>& requests() { + return requests_; + } + RequestPriority priority() const { return priority_; } + + protected: + // Set a new `QuicSessionRequest`'s expectations about which callbacks + // will be invoked. This is called in `AddRequest`. + virtual void SetRequestExpectations(QuicSessionRequest* request) = 0; + + // Update the priority of any ongoing work in this job. + virtual void UpdatePriority(RequestPriority old_priority, + RequestPriority new_priority); + + const raw_ptr pool_; + const QuicSessionAliasKey key_; + const std::unique_ptr client_config_handle_; + RequestPriority priority_; + const NetLogWithSource net_log_; + std::set> requests_; +}; + +} // namespace net + +#endif // NET_QUIC_QUIC_SESSION_POOL_JOB_H_ diff --git a/naiveproxy/src/net/quic/quic_session_pool_peer.cc b/naiveproxy/src/net/quic/quic_session_pool_peer.cc index 1701c60246..714a45fd89 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_peer.cc +++ b/naiveproxy/src/net/quic/quic_session_pool_peer.cc @@ -8,16 +8,23 @@ #include #include "base/task/sequenced_task_runner.h" +#include "net/base/network_anonymization_key.h" +#include "net/base/privacy_mode.h" +#include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/dns/public/secure_dns_policy.h" #include "net/quic/platform/impl/quic_chromium_clock.h" #include "net/quic/quic_chromium_client_session.h" #include "net/quic/quic_http_stream.h" +#include "net/quic/quic_session_key.h" #include "net/quic/quic_session_pool.h" +#include "net/socket/socket_tag.h" #include "net/test/cert_test_util.h" #include "net/test/test_data_directory.h" #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_crypto_client_config.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "url/scheme_host_port.h" using std::string; @@ -40,18 +47,21 @@ bool QuicSessionPoolPeer::HasActiveSession( QuicSessionPool* factory, const quic::QuicServerId& server_id, const NetworkAnonymizationKey& network_anonymization_key, - bool require_dns_https_alpn) { + const ProxyChain& proxy_chain, + SessionUsage session_usage) { return factory->HasActiveSession( - QuicSessionKey(server_id, SocketTag(), network_anonymization_key, - SecureDnsPolicy::kAllow, require_dns_https_alpn)); + QuicSessionKey(server_id, proxy_chain, session_usage, SocketTag(), + network_anonymization_key, SecureDnsPolicy::kAllow, + /*require_dns_https_alpn=*/false)); } bool QuicSessionPoolPeer::HasActiveJob(QuicSessionPool* factory, const quic::QuicServerId& server_id, bool require_dns_https_alpn) { - return factory->HasActiveJob( - QuicSessionKey(server_id, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, require_dns_https_alpn)); + return factory->HasActiveJob(QuicSessionKey( + server_id, ProxyChain::Direct(), SessionUsage::kDestination, SocketTag(), + NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + require_dns_https_alpn)); } // static @@ -59,8 +69,9 @@ QuicChromiumClientSession* QuicSessionPoolPeer::GetPendingSession( QuicSessionPool* factory, const quic::QuicServerId& server_id, url::SchemeHostPort destination) { - QuicSessionKey session_key(server_id, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, + QuicSessionKey session_key(server_id, ProxyChain::Direct(), + SessionUsage::kDestination, SocketTag(), + NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, /*require_dns_https_alpn=*/false); QuicSessionPool::QuicSessionAliasKey key(std::move(destination), session_key); DCHECK(factory->HasActiveJob(session_key)); @@ -74,29 +85,14 @@ QuicChromiumClientSession* QuicSessionPoolPeer::GetActiveSession( const quic::QuicServerId& server_id, const NetworkAnonymizationKey& network_anonymization_key, bool require_dns_https_alpn) { - QuicSessionKey session_key(server_id, SocketTag(), network_anonymization_key, - SecureDnsPolicy::kAllow, require_dns_https_alpn); + QuicSessionKey session_key(server_id, ProxyChain::Direct(), + SessionUsage::kDestination, SocketTag(), + network_anonymization_key, SecureDnsPolicy::kAllow, + require_dns_https_alpn); DCHECK(factory->HasActiveSession(session_key)); return factory->active_sessions_[session_key]; } -bool QuicSessionPoolPeer::HasLiveSession(QuicSessionPool* factory, - url::SchemeHostPort destination, - const quic::QuicServerId& server_id, - bool require_dns_https_alpn) { - QuicSessionKey session_key = - QuicSessionKey(server_id, SocketTag(), NetworkAnonymizationKey(), - SecureDnsPolicy::kAllow, require_dns_https_alpn); - QuicSessionPool::QuicSessionAliasKey alias_key(std::move(destination), - session_key); - for (const auto& it : factory->all_sessions_) { - if (it.second == alias_key) { - return true; - } - } - return false; -} - bool QuicSessionPoolPeer::IsLiveSession(QuicSessionPool* factory, QuicChromiumClientSession* session) { for (const auto& it : factory->all_sessions_) { @@ -142,45 +138,6 @@ bool QuicSessionPoolPeer::CryptoConfigCacheIsEmpty( network_anonymization_key); } -void QuicSessionPoolPeer::CacheDummyServerConfig( - QuicSessionPool* factory, - const quic::QuicServerId& quic_server_id, - const NetworkAnonymizationKey& network_anonymization_key) { - // Minimum SCFG that passes config validation checks. - const char scfg[] = {// SCFG - 0x53, 0x43, 0x46, 0x47, - // num entries - 0x01, 0x00, - // padding - 0x00, 0x00, - // EXPY - 0x45, 0x58, 0x50, 0x59, - // EXPY end offset - 0x08, 0x00, 0x00, 0x00, - // Value - '1', '2', '3', '4', '5', '6', '7', '8'}; - - string server_config(reinterpret_cast(&scfg), sizeof(scfg)); - string source_address_token("test_source_address_token"); - string signature("test_signature"); - - std::vector certs; - // Load a certificate that is valid for *.example.org - scoped_refptr cert( - ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem")); - DCHECK(cert); - certs.emplace_back(x509_util::CryptoBufferAsStringPiece(cert->cert_buffer())); - - std::unique_ptr crypto_config_handle = - GetCryptoConfig(factory, network_anonymization_key); - quic::QuicCryptoClientConfig::CachedState* cached = - crypto_config_handle->GetConfig()->LookupOrCreate(quic_server_id); - quic::QuicChromiumClock clock; - cached->Initialize(server_config, source_address_token, certs, "", "", - signature, clock.WallNow(), quic::QuicWallTime::Zero()); - DCHECK(!cached->certs().empty()); -} - size_t QuicSessionPoolPeer::GetNumDegradingSessions(QuicSessionPool* factory) { return factory->connectivity_monitor_.GetNumDegradingSessions(); } diff --git a/naiveproxy/src/net/quic/quic_session_pool_peer.h b/naiveproxy/src/net/quic/quic_session_pool_peer.h index 6788f58549..31b80cda36 100644 --- a/naiveproxy/src/net/quic/quic_session_pool_peer.h +++ b/naiveproxy/src/net/quic/quic_session_pool_peer.h @@ -15,6 +15,8 @@ #include "net/base/host_port_pair.h" #include "net/base/network_anonymization_key.h" #include "net/base/privacy_mode.h" +#include "net/base/session_usage.h" +#include "net/quic/quic_session_key.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_time.h" @@ -48,9 +50,9 @@ class QuicSessionPoolPeer { static bool HasActiveSession( QuicSessionPool* factory, const quic::QuicServerId& server_id, - const NetworkAnonymizationKey& network_anonymization_key = - NetworkAnonymizationKey(), - bool require_dns_https_alpn = false); + const NetworkAnonymizationKey& network_anonymization_key, + const ProxyChain& proxy_chain = ProxyChain::Direct(), + SessionUsage session_usage = SessionUsage::kDestination); static bool HasActiveJob(QuicSessionPool* factory, const quic::QuicServerId& server_id, @@ -68,11 +70,6 @@ class QuicSessionPoolPeer { NetworkAnonymizationKey(), bool require_dns_https_alpn = false); - static bool HasLiveSession(QuicSessionPool* factory, - url::SchemeHostPort destination, - const quic::QuicServerId& server_id, - bool require_dns_https_alpn = false); - static bool IsLiveSession(QuicSessionPool* factory, QuicChromiumClientSession* session); @@ -90,22 +87,11 @@ class QuicSessionPoolPeer { static void SetYieldAfterDuration(QuicSessionPool* factory, quic::QuicTime::Delta yield_after_duration); - static size_t GetNumberOfActiveJobs(QuicSessionPool* factory, - const quic::QuicServerId& server_id); - static bool CryptoConfigCacheIsEmpty( QuicSessionPool* factory, const quic::QuicServerId& quic_server_id, const NetworkAnonymizationKey& network_anonymization_key); - // Creates a dummy QUIC server config and caches it. Caller must be holding - // onto a QuicCryptoClientConfigHandle for the corresponding - // |network_anonymization_key|. - static void CacheDummyServerConfig( - QuicSessionPool* factory, - const quic::QuicServerId& quic_server_id, - const NetworkAnonymizationKey& network_anonymization_key); - static size_t GetNumDegradingSessions(QuicSessionPool* factory); static void SetAlarmFactory( diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.cc b/naiveproxy/src/net/quic/quic_test_packet_maker.cc index 8821a11804..0dd8cf26dd 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.cc +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.cc @@ -15,8 +15,10 @@ #include "net/quic/quic_http_utils.h" #include "net/spdy/spdy_http_utils.h" #include "net/third_party/quiche/src/quiche/quic/core/http/http_constants.h" +#include "net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_framer.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h" @@ -82,6 +84,10 @@ quic::QuicFrames CloneFrames(const quic::QuicFrames& frames) { frame.ack_frequency_frame = new quic::QuicAckFrequencyFrame(*frame.ack_frequency_frame); break; + case quic::RESET_STREAM_AT_FRAME: + frame.reset_stream_at_frame = + new quic::QuicResetStreamAtFrame(*frame.reset_stream_at_frame); + break; case quic::NUM_FRAME_TYPES: DCHECK(false) << "Cannot clone frame type: " << frame.type; @@ -104,7 +110,8 @@ QuicTestPacketMaker::QuicTestPacketMaker(quic::ParsedQuicVersion version, connection_id_(connection_id), clock_(clock), host_(host), - qpack_encoder_(&decoder_stream_error_delegate_), + qpack_encoder_(&decoder_stream_error_delegate_, + quic::HuffmanEncoding::kEnabled), perspective_(perspective), client_priority_uses_incremental_(client_priority_uses_incremental), use_priority_header_(use_priority_header) { @@ -663,9 +670,10 @@ std::unique_ptr QuicTestPacketMaker::MakeAckPacket( uint64_t packet_number, uint64_t first_received, uint64_t largest_received, - uint64_t smallest_received) { + uint64_t smallest_received, + std::optional ecn) { InitializeHeader(packet_number); - AddQuicAckFrame(first_received, largest_received, smallest_received); + AddQuicAckFrame(first_received, largest_received, smallest_received, ecn); return BuildPacket(); } @@ -1137,21 +1145,24 @@ void QuicTestPacketMaker::AddQuicAckFrame(uint64_t largest_received, AddQuicAckFrame(1, largest_received, smallest_received); } -void QuicTestPacketMaker::AddQuicAckFrame(uint64_t first_received, - uint64_t largest_received, - uint64_t smallest_received) { +void QuicTestPacketMaker::AddQuicAckFrame( + uint64_t first_received, + uint64_t largest_received, + uint64_t smallest_received, + std::optional ecn) { auto* ack_frame = new quic::QuicAckFrame; ack_frame->largest_acked = quic::QuicPacketNumber(largest_received); ack_frame->ack_delay_time = quic::QuicTime::Delta::Zero(); for (uint64_t i = smallest_received; i <= largest_received; ++i) { - ack_frame->received_packet_times.push_back( - std::make_pair(quic::QuicPacketNumber(i), clock_->Now())); + ack_frame->received_packet_times.emplace_back(quic::QuicPacketNumber(i), + clock_->Now()); } if (largest_received > 0) { DCHECK_GE(largest_received, first_received); ack_frame->packets.AddRange(quic::QuicPacketNumber(first_received), quic::QuicPacketNumber(largest_received + 1)); } + ack_frame->ecn_counters = ecn; frames_.push_back(quic::QuicFrame(ack_frame)); DVLOG(1) << "Adding frame: " << frames_.back(); } @@ -1289,7 +1300,8 @@ std::unique_ptr QuicTestPacketMaker::BuildPacketImpl( buffer, quic::kMaxOutgoingPacketSize); EXPECT_NE(0u, encrypted_size); quic::QuicReceivedPacket encrypted(buffer, encrypted_size, clock_->Now(), - false); + false, 0, true, nullptr, 0, false, + ecn_codepoint_); if (save_packet_frames_) { saved_frames_[header_.packet_number] = frames_copy; } else { diff --git a/naiveproxy/src/net/quic/quic_test_packet_maker.h b/naiveproxy/src/net/quic/quic_test_packet_maker.h index 88cb513f99..77a487fb04 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_maker.h +++ b/naiveproxy/src/net/quic/quic_test_packet_maker.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -21,6 +22,7 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_stream_frame_data_producer.h" +#include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/mock_random.h" #include "net/third_party/quiche/src/quiche/quic/test_tools/qpack/qpack_test_utils.h" @@ -276,7 +278,8 @@ class QuicTestPacketMaker { uint64_t packet_number, uint64_t first_received, uint64_t largest_received, - uint64_t smallest_received); + uint64_t smallest_received, + std::optional ecn = std::nullopt); std::unique_ptr MakeDataPacket( uint64_t packet_number, @@ -422,6 +425,8 @@ class QuicTestPacketMaker { spdy::Http2HeaderBlock headers, size_t* encoded_data_length); + void set_ecn_codepoint(quic::QuicEcnCodepoint ecn) { ecn_codepoint_ = ecn; } + private: // Initialize header of next packet to build. void InitializeHeader(uint64_t packet_number); @@ -452,7 +457,8 @@ class QuicTestPacketMaker { void AddQuicAckFrame(uint64_t largest_received, uint64_t smallest_received); void AddQuicAckFrame(uint64_t first_received, uint64_t largest_received, - uint64_t smallest_received); + uint64_t smallest_received, + std::optional ecn = std::nullopt); void AddQuicRstStreamFrame(quic::QuicStreamId stream_id, quic::QuicRstStreamErrorCode error_code); void AddQuicConnectionCloseFrame(quic::QuicErrorCode quic_error, @@ -527,6 +533,10 @@ class QuicTestPacketMaker { quic::QuicPacketHeader header_; quic::QuicFrames frames_; std::unique_ptr data_producer_; + + // Explicit Congestion Notification (ECN) codepoint to use when making + // packets. + quic::QuicEcnCodepoint ecn_codepoint_ = quic::ECN_NOT_ECT; }; } // namespace net::test diff --git a/naiveproxy/src/net/quic/quic_test_packet_printer.cc b/naiveproxy/src/net/quic/quic_test_packet_printer.cc index 7d6f9b2c01..a33164c3fa 100644 --- a/naiveproxy/src/net/quic/quic_test_packet_printer.cc +++ b/naiveproxy/src/net/quic/quic_test_packet_printer.cc @@ -15,6 +15,8 @@ namespace quic { +namespace { + class QuicPacketPrinter : public QuicFramerVisitorInterface { public: explicit QuicPacketPrinter(QuicFramer* framer, std::ostream* output) @@ -44,7 +46,7 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { *output_ << "OnRetryPacket\n"; } bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override { - *output_ << "OnUnauthenticatedPublicHeader: " << header << "\n"; + *output_ << "OnUnauthenticatedPublicHeader: " << header; return true; } bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override { @@ -95,7 +97,7 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { return true; } bool OnAckFrameEnd(QuicPacketNumber start, - const absl::optional& ecn_counts) override { + const std::optional& ecn_counts) override { *output_ << "OnAckFrameEnd, start: " << start << ", " << ecn_counts.value_or(QuicEcnCounts()).ToString() << "\n"; return true; @@ -195,6 +197,10 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { *output_ << "OnAckFrequencyFrame: " << frame; return true; } + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override { + *output_ << "OnResetStreamAtFrame: " << frame; + return true; + } void OnPacketComplete() override { *output_ << "OnPacketComplete\n"; } bool IsValidStatelessResetToken( const StatelessResetToken& token) const override { @@ -211,6 +217,8 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { mutable raw_ptr output_; }; +} // namespace + } // namespace quic namespace net { diff --git a/naiveproxy/src/net/quic/set_quic_flag.cc b/naiveproxy/src/net/quic/set_quic_flag.cc index 3c9c4cc4a3..b51f13a19a 100644 --- a/naiveproxy/src/net/quic/set_quic_flag.cc +++ b/naiveproxy/src/net/quic/set_quic_flag.cc @@ -53,13 +53,13 @@ void SetQuicFlagByName(const std::string& flag_name, const std::string& value) { #include "net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) \ +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) \ if (flag_name == "FLAGS_" #flag) { \ SetQuicFlagByName_##type(&FLAGS_##flag, value); \ return; \ } -#include "net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#include "net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG } } // namespace net diff --git a/naiveproxy/src/net/quic/web_transport_client.cc b/naiveproxy/src/net/quic/web_transport_client.cc index ee9b5f67af..cf19e956c2 100644 --- a/naiveproxy/src/net/quic/web_transport_client.cc +++ b/naiveproxy/src/net/quic/web_transport_client.cc @@ -21,7 +21,7 @@ class FailedWebTransportClient : public WebTransportClient { /*safe_to_report_details=*/true), visitor_(visitor) {} void Connect() override { visitor_->OnConnectionFailed(error_); } - void Close(const absl::optional& close_info) override { + void Close(const std::optional& close_info) override { NOTREACHED(); } diff --git a/naiveproxy/src/net/quic/web_transport_client.h b/naiveproxy/src/net/quic/web_transport_client.h index fd4b312846..1c3e9ceaf1 100644 --- a/naiveproxy/src/net/quic/web_transport_client.h +++ b/naiveproxy/src/net/quic/web_transport_client.h @@ -5,6 +5,7 @@ #ifndef NET_QUIC_WEB_TRANSPORT_CLIENT_H_ #define NET_QUIC_WEB_TRANSPORT_CLIENT_H_ +#include #include #include "base/memory/scoped_refptr.h" @@ -14,7 +15,6 @@ #include "net/third_party/quiche/src/quiche/quic/core/crypto/web_transport_fingerprint_proof_verifier.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/third_party/quiche/src/quiche/quic/core/web_transport_interface.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -81,7 +81,7 @@ class NET_EXPORT WebTransportClientVisitor { virtual void OnConnectionFailed(const WebTransportError& error) = 0; // CONNECTED -> CLOSED virtual void OnClosed( - const absl::optional& close_info) = 0; + const std::optional& close_info) = 0; // CONNECTED -> FAILED virtual void OnError(const WebTransportError& error) = 0; @@ -91,7 +91,7 @@ class NET_EXPORT WebTransportClientVisitor { virtual void OnCanCreateNewOutgoingBidirectionalStream() = 0; virtual void OnCanCreateNewOutgoingUnidirectionalStream() = 0; virtual void OnDatagramProcessed( - absl::optional status) = 0; + std::optional status) = 0; }; // Parameters that determine the way WebTransport session is established. @@ -126,7 +126,7 @@ class NET_EXPORT WebTransportClient { // when the state is CONNECTED. The associated visitor is still waiting for // OnClosed or OnError to be called. virtual void Close( - const absl::optional& close_info) = 0; + const std::optional& close_info) = 0; // session() can be nullptr in states other than CONNECTED. virtual quic::WebTransportSession* session() = 0; diff --git a/naiveproxy/src/net/reporting/reporting_cache.h b/naiveproxy/src/net/reporting/reporting_cache.h index 3fe4c2a5ab..83236f4438 100644 --- a/naiveproxy/src/net/reporting/reporting_cache.h +++ b/naiveproxy/src/net/reporting/reporting_cache.h @@ -6,6 +6,7 @@ #define NET_REPORTING_REPORTING_CACHE_H_ #include +#include #include #include #include @@ -21,7 +22,6 @@ #include "net/reporting/reporting_endpoint.h" #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_report.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -68,7 +68,7 @@ class NET_EXPORT ReportingCache { // All other parameters correspond to the desired values for the relevant // fields in ReportingReport. virtual void AddReport( - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const GURL& url, const std::string& user_agent, diff --git a/naiveproxy/src/net/reporting/reporting_cache_impl.cc b/naiveproxy/src/net/reporting/reporting_cache_impl.cc index 01885b15c1..064616adb7 100644 --- a/naiveproxy/src/net/reporting/reporting_cache_impl.cc +++ b/naiveproxy/src/net/reporting/reporting_cache_impl.cc @@ -5,6 +5,7 @@ #include "net/reporting/reporting_cache_impl.h" #include +#include #include #include #include @@ -18,7 +19,6 @@ #include "net/base/network_anonymization_key.h" #include "net/base/url_util.h" #include "net/log/net_log.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -30,7 +30,7 @@ ReportingCacheImpl::ReportingCacheImpl(ReportingContext* context) ReportingCacheImpl::~ReportingCacheImpl() = default; void ReportingCacheImpl::AddReport( - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const GURL& url, const std::string& user_agent, @@ -607,7 +607,7 @@ void ReportingCacheImpl::AddClientsLoadedFromStore( auto endpoints_it = loaded_endpoints.begin(); auto endpoint_groups_it = loaded_endpoint_groups.begin(); - absl::optional client; + std::optional client; while (endpoint_groups_it != loaded_endpoint_groups.end() && endpoints_it != loaded_endpoints.end()) { @@ -642,10 +642,9 @@ void ReportingCacheImpl::AddClientsLoadedFromStore( ++endpoints_it; continue; } - EndpointMap::iterator inserted = endpoints_.insert( - std::make_pair(group_key, std::move(*endpoints_it))); - endpoint_its_by_url_.insert( - std::make_pair(inserted->second.info.url, inserted)); + EndpointMap::iterator inserted = + endpoints_.emplace(group_key, std::move(*endpoints_it)); + endpoint_its_by_url_.emplace(inserted->second.info.url, inserted); ++cur_group_endpoints_count; ++endpoints_it; } @@ -656,12 +655,12 @@ void ReportingCacheImpl::AddClientsLoadedFromStore( client->origin != group_key.origin) { // Store the old client and start a new one. if (client) { - ClientMap::iterator client_it = clients_.insert( - std::make_pair(client->origin.host(), std::move(*client))); + ClientMap::iterator client_it = + clients_.emplace(client->origin.host(), std::move(*client)); EnforcePerClientAndGlobalEndpointLimits(client_it); } DCHECK(FindClientIt(group_key) == clients_.end()); - client = absl::make_optional( + client = std::make_optional( Client(group_key.network_anonymization_key, group_key.origin)); } DCHECK(client.has_value()); @@ -669,7 +668,7 @@ void ReportingCacheImpl::AddClientsLoadedFromStore( client->endpoint_count += cur_group_endpoints_count; client->last_used = std::max(client->last_used, group.last_used); - endpoint_groups_.insert(std::make_pair(group_key, std::move(group))); + endpoint_groups_.emplace(group_key, std::move(group)); ++endpoint_groups_it; } @@ -677,8 +676,8 @@ void ReportingCacheImpl::AddClientsLoadedFromStore( if (client) { DCHECK(FindClientIt(client->network_anonymization_key, client->origin) == clients_.end()); - ClientMap::iterator client_it = clients_.insert( - std::make_pair(client->origin.host(), std::move(*client))); + ClientMap::iterator client_it = + clients_.emplace(client->origin.host(), std::move(*client)); EnforcePerClientAndGlobalEndpointLimits(client_it); } @@ -915,7 +914,7 @@ void ReportingCacheImpl::SetEndpointForTesting( if (client_it == clients_.end()) { Client new_client(group_key.network_anonymization_key, group_key.origin); std::string domain = group_key.origin.host(); - client_it = clients_.insert(std::make_pair(domain, std::move(new_client))); + client_it = clients_.emplace(domain, std::move(new_client)); } base::Time now = clock().Now(); @@ -925,9 +924,7 @@ void ReportingCacheImpl::SetEndpointForTesting( if (group_it == endpoint_groups_.end()) { CachedReportingEndpointGroup new_group(group_key, include_subdomains, expires, now); - group_it = - endpoint_groups_.insert(std::make_pair(group_key, std::move(new_group))) - .first; + group_it = endpoint_groups_.emplace(group_key, std::move(new_group)).first; client_it->second.endpoint_group_names.insert(group_key.group_name); } else { // Otherwise, update the existing entry @@ -946,8 +943,7 @@ void ReportingCacheImpl::SetEndpointForTesting( info.priority = priority; info.weight = weight; ReportingEndpoint new_endpoint(group_key, info); - endpoint_it = - endpoints_.insert(std::make_pair(group_key, std::move(new_endpoint))); + endpoint_it = endpoints_.emplace(group_key, std::move(new_endpoint)); AddEndpointItToIndex(endpoint_it); ++client_it->second.endpoint_count; } else { @@ -1027,8 +1023,8 @@ void ReportingCacheImpl::ConsistencyCheckClients() const { total_endpoint_count += client.endpoint_count; total_endpoint_group_count += ConsistencyCheckClient(domain, client); - auto inserted = nik_origin_pairs_in_cache.insert( - std::make_pair(client.network_anonymization_key, client.origin)); + auto inserted = nik_origin_pairs_in_cache.emplace( + client.network_anonymization_key, client.origin); // We have not seen a duplicate client with the same NAK and origin. DCHECK(inserted.second); } @@ -1191,8 +1187,7 @@ ReportingCacheImpl::ClientMap::iterator ReportingCacheImpl::AddOrUpdateClient( // Add a new client for this NAK and origin. if (client_it == clients_.end()) { std::string domain = new_client.origin.host(); - client_it = clients_.insert( - std::make_pair(std::move(domain), std::move(new_client))); + client_it = clients_.emplace(std::move(domain), std::move(new_client)); } else { // If an entry already existed, just update it. Client& old_client = client_it->second; @@ -1217,8 +1212,7 @@ void ReportingCacheImpl::AddOrUpdateEndpointGroup( if (context_->IsClientDataPersisted()) store()->AddReportingEndpointGroup(new_group); - endpoint_groups_.insert( - std::make_pair(new_group.group_key, std::move(new_group))); + endpoint_groups_.emplace(new_group.group_key, std::move(new_group)); return; } @@ -1244,8 +1238,8 @@ void ReportingCacheImpl::AddOrUpdateEndpoint(ReportingEndpoint new_endpoint) { if (context_->IsClientDataPersisted()) store()->AddReportingEndpoint(new_endpoint); - endpoint_it = endpoints_.insert( - std::make_pair(new_endpoint.group_key, std::move(new_endpoint))); + endpoint_it = + endpoints_.emplace(new_endpoint.group_key, std::move(new_endpoint)); AddEndpointItToIndex(endpoint_it); // If the client already exists, update its endpoint count. @@ -1292,7 +1286,7 @@ void ReportingCacheImpl::RemoveEndpointsInGroupOtherThan( // This may invalidate |group_it| (and also possibly |client_it|), but only // if we are processing the last remaining endpoint in the group. - absl::optional next_it = + std::optional next_it = RemoveEndpointInternal(client_it, group_it, it); if (!next_it.has_value()) return; @@ -1348,7 +1342,7 @@ void ReportingCacheImpl::MarkEndpointGroupAndClientUsed( store()->UpdateReportingEndpointGroupAccessTime(group_it->second); } -absl::optional +std::optional ReportingCacheImpl::RemoveEndpointInternal(ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, EndpointMap::iterator endpoint_it) { @@ -1362,7 +1356,7 @@ ReportingCacheImpl::RemoveEndpointInternal(ClientMap::iterator client_it, // be removed if it becomes empty. if (endpoints_.count(group_key) == 1) { RemoveEndpointGroupInternal(client_it, group_it); - return absl::nullopt; + return std::nullopt; } // Otherwise, there are other endpoints in the group, so there is no chance // of needing to remove the group/client. Just remove this endpoint and @@ -1375,7 +1369,7 @@ ReportingCacheImpl::RemoveEndpointInternal(ClientMap::iterator client_it, return endpoints_.erase(endpoint_it); } -absl::optional +std::optional ReportingCacheImpl::RemoveEndpointGroupInternal( ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, @@ -1417,7 +1411,7 @@ ReportingCacheImpl::RemoveEndpointGroupInternal( if (client.endpoint_count == 0) { DCHECK(client.endpoint_group_names.empty()); clients_.erase(client_it); - return absl::nullopt; + return std::nullopt; } return rv; } @@ -1592,7 +1586,7 @@ bool ReportingCacheImpl::RemoveExpiredOrStaleGroups( void ReportingCacheImpl::AddEndpointItToIndex( EndpointMap::iterator endpoint_it) { const GURL& url = endpoint_it->second.info.url; - endpoint_its_by_url_.insert(std::make_pair(url, endpoint_it)); + endpoint_its_by_url_.emplace(url, endpoint_it); } void ReportingCacheImpl::RemoveEndpointItFromIndex( diff --git a/naiveproxy/src/net/reporting/reporting_cache_impl.h b/naiveproxy/src/net/reporting/reporting_cache_impl.h index 225f063cc1..6e71ba9231 100644 --- a/naiveproxy/src/net/reporting/reporting_cache_impl.h +++ b/naiveproxy/src/net/reporting/reporting_cache_impl.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -28,7 +29,6 @@ #include "net/reporting/reporting_endpoint.h" #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_report.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -44,7 +44,7 @@ class ReportingCacheImpl : public ReportingCache { ~ReportingCacheImpl() override; // ReportingCache implementation - void AddReport(const absl::optional& reporting_source, + void AddReport(const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const GURL& url, const std::string& user_agent, @@ -276,10 +276,10 @@ class ReportingCacheImpl : public ReportingCache { // Also takes iterators to the client and endpoint group to avoid repeated // lookups. May cause the client and/or group to be removed if they become // empty, which would invalidate those iterators. - // Returns the iterator following the endpoint removed, or absl::nullopt if + // Returns the iterator following the endpoint removed, or std::nullopt if // either of |group_it| or |client_it| were invalidated. (If |client_it| is // invalidated, then so must |group_it|). - absl::optional RemoveEndpointInternal( + std::optional RemoveEndpointInternal( ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, EndpointMap::iterator endpoint_it); @@ -290,9 +290,9 @@ class ReportingCacheImpl : public ReportingCache { // invalidate |client_it|. If |num_endpoints_removed| is not null, then // |*num_endpoints_removed| is incremented by the number of endpoints // removed. - // Returns the iterator following the endpoint group removed, or absl::nullopt + // Returns the iterator following the endpoint group removed, or std::nullopt // if |client_it| was invalidated. - absl::optional RemoveEndpointGroupInternal( + std::optional RemoveEndpointGroupInternal( ClientMap::iterator client_it, EndpointGroupMap::iterator group_it, size_t* num_endpoints_removed = nullptr); diff --git a/naiveproxy/src/net/reporting/reporting_delivery_agent.cc b/naiveproxy/src/net/reporting/reporting_delivery_agent.cc index 5a8f31a6e6..f9fd48b65f 100644 --- a/naiveproxy/src/net/reporting/reporting_delivery_agent.cc +++ b/naiveproxy/src/net/reporting/reporting_delivery_agent.cc @@ -96,7 +96,7 @@ class Delivery { const NetworkAnonymizationKey& network_anonymization_key, const url::Origin& origin, const GURL& endpoint_url, - const absl::optional reporting_source) + const std::optional reporting_source) : isolation_info(isolation_info), network_anonymization_key(network_anonymization_key), origin(origin), @@ -123,7 +123,7 @@ class Delivery { NetworkAnonymizationKey network_anonymization_key; url::Origin origin; GURL endpoint_url; - absl::optional reporting_source; + std::optional reporting_source; }; explicit Delivery(const Target& target) : target_(target) {} @@ -331,8 +331,8 @@ class ReportingDeliveryAgentImpl : public ReportingDeliveryAgent, if (delivery_it == deliveries.end()) { bool inserted; auto new_delivery = std::make_unique(target); - std::tie(delivery_it, inserted) = deliveries.insert( - std::make_pair(std::move(target), std::move(new_delivery))); + std::tie(delivery_it, inserted) = + deliveries.emplace(std::move(target), std::move(new_delivery)); DCHECK(inserted); } delivery_it->second->AddReports(endpoint, bucket_start, bucket_it); diff --git a/naiveproxy/src/net/reporting/reporting_endpoint.cc b/naiveproxy/src/net/reporting/reporting_endpoint.cc index eb62f5c85e..2fe25db3dc 100644 --- a/naiveproxy/src/net/reporting/reporting_endpoint.cc +++ b/naiveproxy/src/net/reporting/reporting_endpoint.cc @@ -21,13 +21,13 @@ ReportingEndpointGroupKey::ReportingEndpointGroupKey( const url::Origin& origin, const std::string& group_name) : ReportingEndpointGroupKey(network_anonymization_key, - absl::nullopt, + std::nullopt, origin, group_name) {} ReportingEndpointGroupKey::ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, - absl::optional reporting_source, + std::optional reporting_source, const url::Origin& origin, const std::string& group_name) : network_anonymization_key(network_anonymization_key), @@ -41,7 +41,7 @@ ReportingEndpointGroupKey::ReportingEndpointGroupKey( ReportingEndpointGroupKey::ReportingEndpointGroupKey( const ReportingEndpointGroupKey& other, - const absl::optional& reporting_source) + const std::optional& reporting_source) : ReportingEndpointGroupKey(other.network_anonymization_key, reporting_source, other.origin, diff --git a/naiveproxy/src/net/reporting/reporting_endpoint.h b/naiveproxy/src/net/reporting/reporting_endpoint.h index 1b99c0c83d..6d85fa59b4 100644 --- a/naiveproxy/src/net/reporting/reporting_endpoint.h +++ b/naiveproxy/src/net/reporting/reporting_endpoint.h @@ -5,6 +5,7 @@ #ifndef NET_REPORTING_REPORTING_ENDPOINT_H_ #define NET_REPORTING_REPORTING_ENDPOINT_H_ +#include #include #include @@ -12,7 +13,6 @@ #include "base/unguessable_token.h" #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -29,13 +29,13 @@ struct NET_EXPORT ReportingEndpointGroupKey { ReportingEndpointGroupKey( const NetworkAnonymizationKey& network_anonymization_key, - absl::optional reporting_source, + std::optional reporting_source, const url::Origin& origin, const std::string& group_name); ReportingEndpointGroupKey( const ReportingEndpointGroupKey& other, - const absl::optional& reporting_source); + const std::optional& reporting_source); ReportingEndpointGroupKey(const ReportingEndpointGroupKey& other); ReportingEndpointGroupKey(ReportingEndpointGroupKey&& other); @@ -58,7 +58,7 @@ struct NET_EXPORT ReportingEndpointGroupKey { // Source token for the document or worker which configured this endpoint, if // this was configured with the Reporting-Endpoints header. For endpoint // groups configured with the Report-To header, this will be nullopt. - absl::optional reporting_source; + std::optional reporting_source; // Origin that configured this endpoint group. url::Origin origin; diff --git a/naiveproxy/src/net/reporting/reporting_header_parser.cc b/naiveproxy/src/net/reporting/reporting_header_parser.cc index 30f9897c7d..36ecc12973 100644 --- a/naiveproxy/src/net/reporting/reporting_header_parser.cc +++ b/naiveproxy/src/net/reporting/reporting_header_parser.cc @@ -149,7 +149,7 @@ bool ProcessEndpointGroup( } parsed_endpoint_group_out->ttl = base::Seconds(ttl_sec); - absl::optional subdomains_bool = dict->FindBool(kIncludeSubdomainsKey); + std::optional subdomains_bool = dict->FindBool(kIncludeSubdomainsKey); if (subdomains_bool && subdomains_bool.value()) { // Disallow eTLDs from setting include_subdomains endpoint groups. if (registry_controlled_domains::GetRegistryLength( @@ -239,18 +239,18 @@ bool ProcessV1Endpoint(ReportingDelegate* delegate, } // namespace -absl::optional> -ParseReportingEndpoints(const std::string& header) { +std::optional> ParseReportingEndpoints( + const std::string& header) { // Ignore empty header values. Skip logging metric to maintain parity with // ReportingHeaderType::kReportToInvalid. if (header.empty()) - return absl::nullopt; - absl::optional header_dict = + return std::nullopt; + std::optional header_dict = structured_headers::ParseDictionary(header); if (!header_dict) { ReportingHeaderParser::RecordReportingHeaderType( ReportingHeaderParser::ReportingHeaderType::kReportingEndpointsInvalid); - return absl::nullopt; + return std::nullopt; } base::flat_map parsed_header; for (const structured_headers::DictionaryMember& entry : *header_dict) { @@ -259,7 +259,7 @@ ParseReportingEndpoints(const std::string& header) { ReportingHeaderParser::RecordReportingHeaderType( ReportingHeaderParser::ReportingHeaderType:: kReportingEndpointsInvalid); - return absl::nullopt; + return std::nullopt; } const std::string& endpoint_url_string = entry.second.member.front().item.GetString(); diff --git a/naiveproxy/src/net/reporting/reporting_header_parser.h b/naiveproxy/src/net/reporting/reporting_header_parser.h index 76ff3b212e..7bb7ef398b 100644 --- a/naiveproxy/src/net/reporting/reporting_header_parser.h +++ b/naiveproxy/src/net/reporting/reporting_header_parser.h @@ -6,12 +6,12 @@ #define NET_REPORTING_REPORTING_HEADER_PARSER_H_ #include +#include #include "base/containers/flat_map.h" #include "base/values.h" #include "net/base/net_export.h" #include "net/http/structured_headers.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -25,8 +25,8 @@ class ReportingContext; // failed and the header should be ignored; otherwise returns a (possibly // empty) mapping of endpoint names to URLs. NET_EXPORT -absl::optional> -ParseReportingEndpoints(const std::string& header); +std::optional> ParseReportingEndpoints( + const std::string& header); class NET_EXPORT ReportingHeaderParser { public: diff --git a/naiveproxy/src/net/reporting/reporting_report.cc b/naiveproxy/src/net/reporting/reporting_report.cc index ecb36458d4..cecee74746 100644 --- a/naiveproxy/src/net/reporting/reporting_report.cc +++ b/naiveproxy/src/net/reporting/reporting_report.cc @@ -16,7 +16,7 @@ namespace net { ReportingReport::ReportingReport( - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const GURL& url, const std::string& user_agent, diff --git a/naiveproxy/src/net/reporting/reporting_report.h b/naiveproxy/src/net/reporting/reporting_report.h index 27f8d8de2a..bece78c7fb 100644 --- a/naiveproxy/src/net/reporting/reporting_report.h +++ b/naiveproxy/src/net/reporting/reporting_report.h @@ -6,6 +6,7 @@ #define NET_REPORTING_REPORTING_REPORT_H_ #include +#include #include #include "base/time/time.h" @@ -14,7 +15,6 @@ #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" #include "net/reporting/reporting_endpoint.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -40,17 +40,16 @@ struct NET_EXPORT ReportingReport { }; // TODO(chlily): Remove |attempts| argument as it is (almost?) always 0. - ReportingReport( - const absl::optional& reporting_source, - const NetworkAnonymizationKey& network_anonymization_key, - const GURL& url, - const std::string& user_agent, - const std::string& group, - const std::string& type, - base::Value::Dict body, - int depth, - base::TimeTicks queued, - int attempts); + ReportingReport(const std::optional& reporting_source, + const NetworkAnonymizationKey& network_anonymization_key, + const GURL& url, + const std::string& user_agent, + const std::string& group, + const std::string& type, + base::Value::Dict body, + int depth, + base::TimeTicks queued, + int attempts); // Do NOT use this constructor outside of mojo deserialization context. ReportingReport(); @@ -82,7 +81,7 @@ struct NET_EXPORT ReportingReport { // endpoint group without a source. Reports without a source token can only be // delivered to endpoint groups without one. // (Not included in the delivered report.) - absl::optional reporting_source; + std::optional reporting_source; // The NAK of the request that triggered this report. (Not included in the // delivered report.) diff --git a/naiveproxy/src/net/reporting/reporting_service.cc b/naiveproxy/src/net/reporting/reporting_service.cc index 6fce6f700c..e575851232 100644 --- a/naiveproxy/src/net/reporting/reporting_service.cc +++ b/naiveproxy/src/net/reporting/reporting_service.cc @@ -4,6 +4,7 @@ #include "net/reporting/reporting_service.h" +#include #include #include "base/feature_list.h" @@ -25,7 +26,6 @@ #include "net/reporting/reporting_delivery_agent.h" #include "net/reporting/reporting_header_parser.h" #include "net/reporting/reporting_uploader.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -81,7 +81,7 @@ class ReportingServiceImpl : public ReportingService { void QueueReport( const GURL& url, - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const std::string& user_agent, const std::string& group, @@ -120,7 +120,7 @@ class ReportingServiceImpl : public ReportingService { if (header_string.size() > kMaxJsonSize) return; - absl::optional header_value = base::JSONReader::Read( + std::optional header_value = base::JSONReader::Read( "[" + header_string + "]", base::JSON_PARSE_RFC, kMaxJsonDepth); if (!header_value) return; @@ -205,7 +205,7 @@ class ReportingServiceImpl : public ReportingService { } void DoQueueReport( - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, GURL sanitized_url, const std::string& user_agent, diff --git a/naiveproxy/src/net/reporting/reporting_service.h b/naiveproxy/src/net/reporting/reporting_service.h index 0ee67508e4..91f2d7fdc5 100644 --- a/naiveproxy/src/net/reporting/reporting_service.h +++ b/naiveproxy/src/net/reporting/reporting_service.h @@ -6,6 +6,7 @@ #define NET_REPORTING_REPORTING_SERVICE_H_ #include +#include #include #include "base/containers/flat_map.h" @@ -15,7 +16,6 @@ #include "net/base/net_export.h" #include "net/reporting/reporting_cache.h" #include "net/reporting/reporting_cache_observer.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -73,7 +73,7 @@ class NET_EXPORT ReportingService { // will be copied. virtual void QueueReport( const GURL& url, - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const std::string& user_agent, const std::string& group, diff --git a/naiveproxy/src/net/reporting/reporting_test_util.cc b/naiveproxy/src/net/reporting/reporting_test_util.cc index ef4197b524..059d51456c 100644 --- a/naiveproxy/src/net/reporting/reporting_test_util.cc +++ b/naiveproxy/src/net/reporting/reporting_test_util.cc @@ -3,9 +3,9 @@ // found in the LICENSE file. #include "net/reporting/reporting_test_util.h" -#include "base/memory/raw_ptr.h" #include +#include #include #include @@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/json/json_reader.h" #include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "base/strings/stringprintf.h" #include "base/test/simple_test_clock.h" @@ -29,7 +30,6 @@ #include "net/reporting/reporting_policy.h" #include "net/reporting/reporting_uploader.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -58,7 +58,7 @@ class PendingUploadImpl : public TestReportingUploader::PendingUpload { const url::Origin& report_origin() const override { return report_origin_; } const GURL& url() const override { return url_; } const std::string& json() const override { return json_; } - absl::optional GetValue() const override { + std::optional GetValue() const override { return base::JSONReader::Read(json_); } @@ -336,7 +336,7 @@ TestReportingService::~TestReportingService() = default; void TestReportingService::QueueReport( const GURL& url, - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const std::string& user_agent, const std::string& group, diff --git a/naiveproxy/src/net/reporting/reporting_test_util.h b/naiveproxy/src/net/reporting/reporting_test_util.h index f9668b15c5..1e4872599d 100644 --- a/naiveproxy/src/net/reporting/reporting_test_util.h +++ b/naiveproxy/src/net/reporting/reporting_test_util.h @@ -6,6 +6,7 @@ #define NET_REPORTING_REPORTING_TEST_UTIL_H_ #include +#include #include #include #include @@ -24,7 +25,6 @@ #include "net/test/test_with_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace base { @@ -66,7 +66,7 @@ class TestReportingUploader : public ReportingUploader { virtual const url::Origin& report_origin() const = 0; virtual const GURL& url() const = 0; virtual const std::string& json() const = 0; - virtual absl::optional GetValue() const = 0; + virtual std::optional GetValue() const = 0; virtual void Complete(Outcome outcome) = 0; @@ -344,7 +344,7 @@ class TestReportingService : public ReportingService { void QueueReport( const GURL& url, - const absl::optional& reporting_source, + const std::optional& reporting_source, const NetworkAnonymizationKey& network_anonymization_key, const std::string& user_agent, const std::string& group, diff --git a/naiveproxy/src/net/server/http_server_response_info.cc b/naiveproxy/src/net/server/http_server_response_info.cc index db39bf092d..3ce3892780 100644 --- a/naiveproxy/src/net/server/http_server_response_info.cc +++ b/naiveproxy/src/net/server/http_server_response_info.cc @@ -38,7 +38,7 @@ HttpServerResponseInfo HttpServerResponseInfo::CreateFor500( void HttpServerResponseInfo::AddHeader(const std::string& name, const std::string& value) { - headers_.push_back(std::make_pair(name, value)); + headers_.emplace_back(name, value); } void HttpServerResponseInfo::SetBody(const std::string& body, diff --git a/naiveproxy/src/net/socket/client_socket_handle.cc b/naiveproxy/src/net/socket/client_socket_handle.cc index 35d15c24b4..54712c1224 100644 --- a/naiveproxy/src/net/socket/client_socket_handle.cc +++ b/naiveproxy/src/net/socket/client_socket_handle.cc @@ -31,7 +31,7 @@ ClientSocketHandle::~ClientSocketHandle() { int ClientSocketHandle::Init( const ClientSocketPool::GroupId& group_id, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, ClientSocketPool::RespectLimits respect_limits, diff --git a/naiveproxy/src/net/socket/client_socket_handle.h b/naiveproxy/src/net/socket/client_socket_handle.h index 2c7b2b6620..a14430bc23 100644 --- a/naiveproxy/src/net/socket/client_socket_handle.h +++ b/naiveproxy/src/net/socket/client_socket_handle.h @@ -6,6 +6,7 @@ #define NET_SOCKET_CLIENT_SOCKET_HANDLE_H_ #include +#include #include #include "base/check.h" @@ -27,7 +28,6 @@ #include "net/socket/connection_attempts.h" #include "net/socket/stream_socket.h" #include "net/ssl/ssl_cert_request_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -89,7 +89,7 @@ class NET_EXPORT ClientSocketHandle { int Init( const ClientSocketPool::GroupId& group_id, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, ClientSocketPool::RespectLimits respect_limits, diff --git a/naiveproxy/src/net/socket/client_socket_pool.cc b/naiveproxy/src/net/socket/client_socket_pool.cc index c394906138..901d7651aa 100644 --- a/naiveproxy/src/net/socket/client_socket_pool.cc +++ b/naiveproxy/src/net/socket/client_socket_pool.cc @@ -5,14 +5,18 @@ #include "net/socket/client_socket_pool.h" #include +#include #include +#include #include "base/check_op.h" #include "base/feature_list.h" #include "base/functional/bind.h" +#include "base/strings/strcat.h" #include "net/base/features.h" #include "net/base/host_port_pair.h" #include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_proxy_connect_job.h" #include "net/log/net_log_event_type.h" @@ -24,6 +28,7 @@ #include "net/socket/stream_socket.h" #include "net/spdy/spdy_session.h" #include "net/spdy/spdy_session_pool.h" +#include "net/ssl/ssl_config.h" #include "url/gurl.h" #include "url/scheme_host_port.h" #include "url/url_constants.h" @@ -57,18 +62,43 @@ OnHostResolutionCallbackResult OnHostResolution( spdy_session_key, is_for_websockets, endpoint_results, aliases); } +std::string_view GetPrivacyModeGroupIdPrefix(PrivacyMode privacy_mode) { + switch (privacy_mode) { + case PrivacyMode::PRIVACY_MODE_DISABLED: + return ""; + case PrivacyMode::PRIVACY_MODE_ENABLED: + return "pm/"; + case PrivacyMode::PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS: + return "pmwocc/"; + case PrivacyMode::PRIVACY_MODE_ENABLED_PARTITIONED_STATE_ALLOWED: + return "pmpsa/"; + } +} + +std::string_view GetSecureDnsPolicyGroupIdPrefix( + SecureDnsPolicy secure_dns_policy) { + switch (secure_dns_policy) { + case SecureDnsPolicy::kAllow: + return ""; + case SecureDnsPolicy::kDisable: + return "dsd/"; + case SecureDnsPolicy::kBootstrap: + return "dns_bootstrap/"; + } +} + } // namespace ClientSocketPool::SocketParams::SocketParams( - std::unique_ptr ssl_config_for_origin) - : ssl_config_for_origin_(std::move(ssl_config_for_origin)) {} + const std::vector& allowed_bad_certs) + : allowed_bad_certs_(allowed_bad_certs) {} ClientSocketPool::SocketParams::~SocketParams() = default; scoped_refptr ClientSocketPool::SocketParams::CreateForHttpForTesting() { return base::MakeRefCounted( - /*ssl_config_for_origin=*/nullptr); + /*allowed_bad_certs=*/std::vector()); } ClientSocketPool::GroupId::GroupId() @@ -107,33 +137,14 @@ ClientSocketPool::GroupId& ClientSocketPool::GroupId::operator=( GroupId&& group_id) = default; std::string ClientSocketPool::GroupId::ToString() const { - std::string result = destination_.Serialize(); - - if (privacy_mode_) - result = "pm/" + result; - - if (NetworkAnonymizationKey::IsPartitioningEnabled()) { - result += " <"; - result += network_anonymization_key_.ToDebugString(); - result += ">"; - } - - switch (secure_dns_policy_) { - case SecureDnsPolicy::kAllow: - break; - case SecureDnsPolicy::kDisable: - result = "dsd/" + result; - break; - case SecureDnsPolicy::kBootstrap: - result = "dns_bootstrap/" + result; - break; - } - - if (disable_cert_network_fetches_) { - result = "disable_cert_network_fetches/" + result; - } - - return result; + return base::StrCat( + {disable_cert_network_fetches_ ? "disable_cert_network_fetches/" : "", + GetSecureDnsPolicyGroupIdPrefix(secure_dns_policy_), + GetPrivacyModeGroupIdPrefix(privacy_mode_), destination_.Serialize(), + NetworkAnonymizationKey::IsPartitioningEnabled() + ? base::StrCat( + {" <", network_anonymization_key_.ToDebugString(), ">"}) + : ""}); } ClientSocketPool::~ClientSocketPool() = default; @@ -174,7 +185,7 @@ std::unique_ptr ClientSocketPool::CreateConnectJob( GroupId group_id, scoped_refptr socket_params, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority request_priority, SocketTag socket_tag, ConnectJob::Delegate* delegate) { @@ -189,10 +200,11 @@ std::unique_ptr ClientSocketPool::CreateConnectJob( &OnHostResolution, common_connect_job_params_->spdy_session_pool, // TODO(crbug.com/1206799): Pass along as SchemeHostPort. SpdySessionKey(HostPortPair::FromSchemeHostPort(group_id.destination()), - proxy_chain, group_id.privacy_mode(), - SpdySessionKey::IsProxySession::kFalse, socket_tag, + group_id.privacy_mode(), proxy_chain, + SessionUsage::kDestination, socket_tag, group_id.network_anonymization_key(), - group_id.secure_dns_policy()), + group_id.secure_dns_policy(), + group_id.disable_cert_network_fetches()), is_for_websockets_); } @@ -215,7 +227,7 @@ std::unique_ptr ClientSocketPool::CreateConnectJob( return connect_job_factory_->CreateConnectJob( group_id.destination(), proxy_chain, proxy_annotation_tag, - socket_params->ssl_config_for_origin(), alpn_mode, force_tunnel, + socket_params->allowed_bad_certs(), alpn_mode, force_tunnel, group_id.privacy_mode(), resolution_callback, request_priority, socket_tag, group_id.network_anonymization_key(), group_id.secure_dns_policy(), group_id.disable_cert_network_fetches(), diff --git a/naiveproxy/src/net/socket/client_socket_pool.h b/naiveproxy/src/net/socket/client_socket_pool.h index f26f7d45b3..aa76fd2d30 100644 --- a/naiveproxy/src/net/socket/client_socket_pool.h +++ b/naiveproxy/src/net/socket/client_socket_pool.h @@ -6,7 +6,9 @@ #define NET_SOCKET_CLIENT_SOCKET_POOL_H_ #include +#include #include +#include #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" @@ -24,7 +26,7 @@ #include "net/log/net_log_capture_mode.h" #include "net/socket/connect_job.h" #include "net/socket/socket_tag.h" -#include "third_party/abseil-cpp/absl/types/optional.h" +#include "net/ssl/ssl_config.h" #include "url/scheme_host_port.h" namespace net { @@ -174,8 +176,10 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { class NET_EXPORT_PRIVATE SocketParams : public base::RefCounted { public: - // For non-SSL requests, `ssl_config_for_origin` argument may be nullptr. - explicit SocketParams(std::unique_ptr ssl_config_for_origin); + // For non-SSL requests, `allowed_bad_certs` argument will be ignored (and + // is likely empty, anyways). + explicit SocketParams( + const std::vector& allowed_bad_certs); SocketParams(const SocketParams&) = delete; SocketParams& operator=(const SocketParams&) = delete; @@ -184,15 +188,15 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { // works for the HTTP case only. static scoped_refptr CreateForHttpForTesting(); - const SSLConfig* ssl_config_for_origin() const { - return ssl_config_for_origin_.get(); + const std::vector& allowed_bad_certs() const { + return allowed_bad_certs_; } private: friend class base::RefCounted; ~SocketParams(); - std::unique_ptr ssl_config_for_origin_; + std::vector allowed_bad_certs_; }; ClientSocketPool(const ClientSocketPool&) = delete; @@ -241,7 +245,7 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { virtual int RequestSocket( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, @@ -265,7 +269,7 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { virtual int RequestSockets( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, int num_sockets, CompletionOnceCallback callback, const NetLogWithSource& net_log) = 0; @@ -361,7 +365,7 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool { GroupId group_id, scoped_refptr socket_params, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority request_priority, SocketTag socket_tag, ConnectJob::Delegate* delegate); diff --git a/naiveproxy/src/net/socket/client_socket_pool_manager.cc b/naiveproxy/src/net/socket/client_socket_pool_manager.cc index 07023b10ad..08aa863584 100644 --- a/naiveproxy/src/net/socket/client_socket_pool_manager.cc +++ b/naiveproxy/src/net/socket/client_socket_pool_manager.cc @@ -5,6 +5,7 @@ #include "net/socket/client_socket_pool_manager.h" #include +#include #include #include "base/check_op.h" @@ -22,7 +23,6 @@ #include "net/socket/client_socket_pool.h" #include "net/socket/connect_job.h" #include "net/ssl/ssl_config.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/scheme_host_port.h" #include "url/url_constants.h" @@ -75,10 +75,10 @@ static_assert(std::size(g_max_sockets_per_proxy_chain) == // entirely. scoped_refptr CreateSocketParams( const ClientSocketPool::GroupId& group_id, - const SSLConfig& ssl_config_for_origin) { + const std::vector& allowed_bad_certs) { bool using_ssl = GURL::SchemeIsCryptographic(group_id.destination().scheme()); return base::MakeRefCounted( - using_ssl ? std::make_unique(ssl_config_for_origin) : nullptr); + using_ssl ? allowed_bad_certs : std::vector()); } int InitSocketPoolHelper( @@ -87,7 +87,7 @@ int InitSocketPoolHelper( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -115,7 +115,7 @@ int InitSocketPoolHelper( std::move(endpoint), privacy_mode, std::move(network_anonymization_key), secure_dns_policy, disable_cert_network_fetches); scoped_refptr socket_params = - CreateSocketParams(connection_group, ssl_config_for_origin); + CreateSocketParams(connection_group, allowed_bad_certs); ClientSocketPool* pool = session->GetSocketPool(socket_pool_type, proxy_info.proxy_chain()); @@ -124,9 +124,9 @@ int InitSocketPoolHelper( if ((request_load_flags & LOAD_IGNORE_LIMITS) != 0) respect_limits = ClientSocketPool::RespectLimits::DISABLED; - absl::optional proxy_annotation = - proxy_info.is_direct() ? absl::nullopt - : absl::optional( + std::optional proxy_annotation = + proxy_info.is_direct() ? std::nullopt + : std::optional( proxy_info.traffic_annotation()); if (num_preconnect_streams) { return pool->RequestSockets(connection_group, std::move(socket_params), @@ -218,7 +218,7 @@ int InitSocketHandleForHttpRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -230,7 +230,7 @@ int InitSocketHandleForHttpRequest( DCHECK(socket_handle); return InitSocketPoolHelper( std::move(endpoint), request_load_flags, request_priority, session, - proxy_info, ssl_config_for_origin, privacy_mode, + proxy_info, allowed_bad_certs, privacy_mode, std::move(network_anonymization_key), secure_dns_policy, socket_tag, net_log, 0, socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback), proxy_auth_callback); @@ -242,7 +242,7 @@ int InitSocketHandleForWebSocketRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, const NetLogWithSource& net_log, @@ -252,7 +252,7 @@ int InitSocketHandleForWebSocketRequest( DCHECK(socket_handle); // QUIC proxies are currently not supported through this method. - DCHECK(!proxy_info.is_quic()); + DCHECK(proxy_info.is_direct() || !proxy_info.proxy_chain().Last().is_quic()); // Expect websocket schemes (ws and wss) to be converted to the http(s) // equivalent. @@ -261,7 +261,7 @@ int InitSocketHandleForWebSocketRequest( return InitSocketPoolHelper( std::move(endpoint), request_load_flags, request_priority, session, - proxy_info, ssl_config_for_origin, privacy_mode, + proxy_info, allowed_bad_certs, privacy_mode, std::move(network_anonymization_key), SecureDnsPolicy::kAllow, SocketTag(), net_log, 0, socket_handle, HttpNetworkSession::WEBSOCKET_SOCKET_POOL, std::move(callback), @@ -274,7 +274,7 @@ int PreconnectSocketsForHttpRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -282,7 +282,7 @@ int PreconnectSocketsForHttpRequest( int num_preconnect_streams, CompletionOnceCallback callback) { // QUIC proxies are currently not supported through this method. - DCHECK(!proxy_info.is_quic()); + DCHECK(proxy_info.is_direct() || !proxy_info.proxy_chain().Last().is_quic()); // Expect websocket schemes (ws and wss) to be converted to the http(s) // equivalent. @@ -291,7 +291,7 @@ int PreconnectSocketsForHttpRequest( return InitSocketPoolHelper( std::move(endpoint), request_load_flags, request_priority, session, - proxy_info, ssl_config_for_origin, privacy_mode, + proxy_info, allowed_bad_certs, privacy_mode, std::move(network_anonymization_key), secure_dns_policy, SocketTag(), net_log, num_preconnect_streams, nullptr, HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback), diff --git a/naiveproxy/src/net/socket/client_socket_pool_manager.h b/naiveproxy/src/net/socket/client_socket_pool_manager.h index 763195b676..e475a528c4 100644 --- a/naiveproxy/src/net/socket/client_socket_pool_manager.h +++ b/naiveproxy/src/net/socket/client_socket_pool_manager.h @@ -9,6 +9,8 @@ #ifndef NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_ #define NET_SOCKET_CLIENT_SOCKET_POOL_MANAGER_H_ +#include + #include "base/values.h" #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" @@ -16,6 +18,7 @@ #include "net/dns/public/secure_dns_policy.h" #include "net/http/http_network_session.h" #include "net/socket/client_socket_pool.h" +#include "net/ssl/ssl_config.h" #include "url/scheme_host_port.h" namespace net { @@ -26,8 +29,6 @@ class NetworkAnonymizationKey; class ProxyInfo; class ProxyChain; -struct SSLConfig; - constexpr int kDefaultMaxSocketsPerProxyChain = 32; class NET_EXPORT_PRIVATE ClientSocketPoolManager { @@ -74,7 +75,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManager { // A helper method that uses the passed in proxy information to initialize a // ClientSocketHandle with the relevant socket pool. Use this method for -// HTTP/HTTPS requests. `ssl_config_for_origin` is only used if the request +// HTTP/HTTPS requests. `allowed_bad_certs` is only used if the request // uses SSL. `resolution_callback` will be invoked after the the hostname is // resolved. If `resolution_callback` does not return OK, then the connection // will be aborted with that value. @@ -84,7 +85,7 @@ int InitSocketHandleForHttpRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, @@ -107,7 +108,7 @@ int InitSocketHandleForWebSocketRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, const NetLogWithSource& net_log, @@ -123,7 +124,7 @@ int PreconnectSocketsForHttpRequest( RequestPriority request_priority, HttpNetworkSession* session, const ProxyInfo& proxy_info, - const SSLConfig& ssl_config_for_origin, + const std::vector& allowed_bad_certs, PrivacyMode privacy_mode, NetworkAnonymizationKey network_anonymization_key, SecureDnsPolicy secure_dns_policy, diff --git a/naiveproxy/src/net/socket/client_socket_pool_manager_impl.cc b/naiveproxy/src/net/socket/client_socket_pool_manager_impl.cc index cefe6cfae8..7cd64a4205 100644 --- a/naiveproxy/src/net/socket/client_socket_pool_manager_impl.cc +++ b/naiveproxy/src/net/socket/client_socket_pool_manager_impl.cc @@ -91,7 +91,7 @@ ClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPool( } std::pair ret = - socket_pools_.insert(std::make_pair(proxy_chain, std::move(new_pool))); + socket_pools_.emplace(proxy_chain, std::move(new_pool)); return ret.first->second.get(); } diff --git a/naiveproxy/src/net/socket/connect_job.cc b/naiveproxy/src/net/socket/connect_job.cc index ae4f305488..519c2be289 100644 --- a/naiveproxy/src/net/socket/connect_job.cc +++ b/naiveproxy/src/net/socket/connect_job.cc @@ -154,13 +154,13 @@ void ConnectJob::set_done_closure(base::OnceClosure done_closure) { done_closure_ = base::ScopedClosureRunner(std::move(done_closure)); } -absl::optional +std::optional ConnectJob::GetHostResolverEndpointResult() const { - return absl::nullopt; + return std::nullopt; } void ConnectJob::SetSocket(std::unique_ptr socket, - absl::optional> dns_aliases) { + std::optional> dns_aliases) { if (socket) { net_log().AddEventReferencingSource(NetLogEventType::CONNECT_JOB_SET_SOCKET, socket->NetLog().source()); @@ -212,7 +212,7 @@ void ConnectJob::LogConnectCompletion(int net_error) { void ConnectJob::OnTimeout() { // Make sure the socket is NULL before calling into |delegate|. - SetSocket(nullptr, absl::nullopt /* dns_aliases */); + SetSocket(nullptr, std::nullopt /* dns_aliases */); OnTimedOutInternal(); diff --git a/naiveproxy/src/net/socket/connect_job.h b/naiveproxy/src/net/socket/connect_job.h index 07440227e0..32cf820798 100644 --- a/naiveproxy/src/net/socket/connect_job.h +++ b/naiveproxy/src/net/socket/connect_job.h @@ -6,6 +6,7 @@ #define NET_SOCKET_CONNECT_JOB_H_ #include +#include #include #include @@ -29,7 +30,6 @@ #include "net/socket/ssl_client_socket.h" #include "net/ssl/ssl_config.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -254,9 +254,9 @@ class NET_EXPORT_PRIVATE ConnectJob { // Returns the `HostResolverEndpointResult` structure corresponding to the // chosen route. Should only be called on a successful connect. If the // `ConnectJob` does not make DNS queries, or does not use the SVCB/HTTPS - // record, it may return `absl::nullopt`, to avoid callers getting confused by + // record, it may return `std::nullopt`, to avoid callers getting confused by // an empty `IPEndPoint` list. - virtual absl::optional + virtual std::optional GetHostResolverEndpointResult() const; const LoadTimingInfo::ConnectTiming& connect_timing() const { @@ -299,7 +299,7 @@ class NET_EXPORT_PRIVATE ConnectJob { } void SetSocket(std::unique_ptr socket, - absl::optional> dns_aliases); + std::optional> dns_aliases); void NotifyDelegateOfCompletion(int rv); void NotifyDelegateOfProxyAuth(const HttpResponseInfo& response, HttpAuthController* auth_controller, diff --git a/naiveproxy/src/net/socket/connect_job_factory.cc b/naiveproxy/src/net/socket/connect_job_factory.cc index bc0a62fc3a..2ab34acfdf 100644 --- a/naiveproxy/src/net/socket/connect_job_factory.cc +++ b/naiveproxy/src/net/socket/connect_job_factory.cc @@ -5,7 +5,9 @@ #include "net/socket/connect_job_factory.h" #include +#include #include +#include #include "base/check.h" #include "base/containers/flat_set.h" @@ -26,7 +28,6 @@ #include "net/socket/transport_connect_job.h" #include "net/ssl/ssl_config.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "url/gurl.h" #include "url/scheme_host_port.h" @@ -171,8 +172,8 @@ ConnectJobFactory::~ConnectJobFactory() = default; std::unique_ptr ConnectJobFactory::CreateConnectJob( url::SchemeHostPort endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, + const std::vector& allowed_bad_certs, ConnectJobFactory::AlpnMode alpn_mode, bool force_tunnel, PrivacyMode privacy_mode, @@ -186,7 +187,7 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( ConnectJob::Delegate* delegate) const { return CreateConnectJob( Endpoint(std::move(endpoint)), proxy_chain, proxy_annotation_tag, - ssl_config_for_origin, alpn_mode, force_tunnel, privacy_mode, + allowed_bad_certs, alpn_mode, force_tunnel, privacy_mode, resolution_callback, request_priority, socket_tag, network_anonymization_key, secure_dns_policy, disable_cert_network_fetches, common_connect_job_params, delegate); @@ -196,8 +197,7 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( bool using_ssl, HostPortPair endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, bool force_tunnel, PrivacyMode privacy_mode, const OnHostResolutionCallback& resolution_callback, @@ -210,7 +210,7 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( SchemelessEndpoint schemeless_endpoint{using_ssl, std::move(endpoint)}; return CreateConnectJob( std::move(schemeless_endpoint), proxy_chain, proxy_annotation_tag, - ssl_config_for_origin, ConnectJobFactory::AlpnMode::kDisabled, + /*allowed_bad_certs=*/{}, ConnectJobFactory::AlpnMode::kDisabled, force_tunnel, privacy_mode, resolution_callback, request_priority, socket_tag, network_anonymization_key, secure_dns_policy, /*disable_cert_network_fetches=*/false, common_connect_job_params, @@ -220,8 +220,8 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( std::unique_ptr ConnectJobFactory::CreateConnectJob( Endpoint endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, + const std::vector& allowed_bad_certs, ConnectJobFactory::AlpnMode alpn_mode, bool force_tunnel, PrivacyMode privacy_mode, @@ -349,10 +349,10 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( // Deal with SSL - which layers on top of any given proxy. if (UsingSsl(endpoint)) { - DCHECK(ssl_config_for_origin); scoped_refptr ssl_tcp_params; - SSLConfig ssl_config = *ssl_config_for_origin; + SSLConfig ssl_config; + ssl_config.allowed_bad_certs = allowed_bad_certs; ConfigureAlpn(endpoint, alpn_mode, network_anonymization_key, *common_connect_job_params, ssl_config, @@ -392,15 +392,15 @@ std::unique_ptr ConnectJobFactory::CreateConnectJob( delegate, /*net_log=*/nullptr); } - const ProxyServer& first_proxy_server = - proxy_chain.GetProxyServer(/*chain_index=*/0); - if (first_proxy_server.is_http_like()) { + const ProxyServer& last_proxy_server = proxy_chain.Last(); + if (http_proxy_params) { + DCHECK(last_proxy_server.is_http_like()); return http_proxy_connect_job_factory_->Create( request_priority, socket_tag, common_connect_job_params, std::move(http_proxy_params), delegate, /*net_log=*/nullptr); } - DCHECK(first_proxy_server.is_socks()); + DCHECK(last_proxy_server.is_socks()); return socks_connect_job_factory_->Create( request_priority, socket_tag, common_connect_job_params, std::move(socks_params), delegate, /*net_log=*/nullptr); diff --git a/naiveproxy/src/net/socket/connect_job_factory.h b/naiveproxy/src/net/socket/connect_job_factory.h index 6966686202..782fb3b698 100644 --- a/naiveproxy/src/net/socket/connect_job_factory.h +++ b/naiveproxy/src/net/socket/connect_job_factory.h @@ -6,6 +6,8 @@ #define NET_SOCKET_CONNECT_JOB_FACTORY_H_ #include +#include +#include #include "net/base/host_port_pair.h" #include "net/base/network_anonymization_key.h" @@ -18,7 +20,7 @@ #include "net/socket/socks_connect_job.h" #include "net/socket/ssl_connect_job.h" #include "net/socket/transport_connect_job.h" -#include "third_party/abseil-cpp/absl/types/optional.h" +#include "net/ssl/ssl_config.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "url/scheme_host_port.h" @@ -84,8 +86,8 @@ class NET_EXPORT_PRIVATE ConnectJobFactory { std::unique_ptr CreateConnectJob( url::SchemeHostPort endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, + const std::vector& allowed_bad_certs, ConnectJobFactory::AlpnMode alpn_mode, bool force_tunnel, PrivacyMode privacy_mode, @@ -104,8 +106,7 @@ class NET_EXPORT_PRIVATE ConnectJobFactory { bool using_ssl, HostPortPair endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, bool force_tunnel, PrivacyMode privacy_mode, const OnHostResolutionCallback& resolution_callback, @@ -120,8 +121,8 @@ class NET_EXPORT_PRIVATE ConnectJobFactory { virtual std::unique_ptr CreateConnectJob( Endpoint endpoint, const ProxyChain& proxy_chain, - const absl::optional& proxy_annotation_tag, - const SSLConfig* ssl_config_for_origin, + const std::optional& proxy_annotation_tag, + const std::vector& allowed_bad_certs, ConnectJobFactory::AlpnMode alpn_mode, bool force_tunnel, PrivacyMode privacy_mode, diff --git a/naiveproxy/src/net/socket/datagram_socket.h b/naiveproxy/src/net/socket/datagram_socket.h index 8961f7c479..c35dc73021 100644 --- a/naiveproxy/src/net/socket/datagram_socket.h +++ b/naiveproxy/src/net/socket/datagram_socket.h @@ -6,6 +6,7 @@ #define NET_SOCKET_DATAGRAM_SOCKET_H_ #include "net/base/net_export.h" +#include "net/socket/diff_serv_code_point.h" namespace net { @@ -47,7 +48,12 @@ class NET_EXPORT_PRIVATE DatagramSocket { // Requests that packets received by this socket have the ECN bit set. Returns // a network error code if there was a problem. - virtual int SetRecvEcn() = 0; + virtual int SetRecvTos() = 0; + + // Sets both parts of the TOS byte in the IP header. DSCP_NO_CHANGE or + // ECN_NO_CHANGE can allow the socket to preserver part of the existing + // setting. + virtual int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) = 0; // If |confirm| is true, then the MSG_CONFIRM flag will be passed to // subsequent writes if it's supported by the platform. @@ -55,6 +61,10 @@ class NET_EXPORT_PRIVATE DatagramSocket { // Gets the NetLog for this socket. virtual const NetLogWithSource& NetLog() const = 0; + + // Returns the TOS byte of the last received datagram, or 0 for sockets which + // do not have the capability. + virtual DscpAndEcn GetLastTos() const = 0; }; } // namespace net diff --git a/naiveproxy/src/net/socket/diff_serv_code_point.h b/naiveproxy/src/net/socket/diff_serv_code_point.h index cf52ee182d..9f22747131 100644 --- a/naiveproxy/src/net/socket/diff_serv_code_point.h +++ b/naiveproxy/src/net/socket/diff_serv_code_point.h @@ -37,6 +37,33 @@ enum DiffServCodePoint { DSCP_LAST = DSCP_CS7 }; +// Explicit Congestion Notification +// See RFC3168 and RFC9330 for details. +enum EcnCodePoint { + ECN_NO_CHANGE = -1, + ECN_FIRST = ECN_NO_CHANGE, + ECN_DEFAULT = 0, + ECN_NOT_ECT = 0, + ECN_ECT1 = 1, + ECN_ECT0 = 2, + ECN_CE = 3, + ECN_LAST = ECN_CE, +}; + +struct DscpAndEcn { + DiffServCodePoint dscp; + EcnCodePoint ecn; +}; + +// Converts an 8-bit IP TOS field to its DSCP and ECN parts. +static inline DscpAndEcn TosToDscpAndEcn(uint8_t tos) { + // Bitmasks to find the DSCP and ECN pieces of the TOS byte. + constexpr uint8_t kEcnMask = 0b11; + constexpr uint8_t kDscpMask = ~kEcnMask; + return DscpAndEcn{static_cast((tos & kDscpMask) >> 2), + static_cast(tos & kEcnMask)}; +} + } // namespace net #endif // NET_SOCKET_DIFF_SERV_CODE_POINT_H_ diff --git a/naiveproxy/src/net/socket/server_socket.cc b/naiveproxy/src/net/socket/server_socket.cc index 5d8c8f05c0..333103a630 100644 --- a/naiveproxy/src/net/socket/server_socket.cc +++ b/naiveproxy/src/net/socket/server_socket.cc @@ -23,7 +23,7 @@ int ServerSocket::ListenWithAddressAndPort(const std::string& address_string, } return Listen(IPEndPoint(ip_address, port), backlog, - /*ipv6_only=*/absl::nullopt); + /*ipv6_only=*/std::nullopt); } int ServerSocket::Accept(std::unique_ptr* socket, diff --git a/naiveproxy/src/net/socket/server_socket.h b/naiveproxy/src/net/socket/server_socket.h index 6fc0b7a06b..d4c8735bcd 100644 --- a/naiveproxy/src/net/socket/server_socket.h +++ b/naiveproxy/src/net/socket/server_socket.h @@ -8,11 +8,11 @@ #include #include +#include #include #include "net/base/completion_once_callback.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -36,7 +36,7 @@ class NET_EXPORT ServerSocket { // default behavior (|true| on Windows, |false| on Posix). virtual int Listen(const IPEndPoint& address, int backlog, - absl::optional ipv6_only) = 0; + std::optional ipv6_only) = 0; // Binds the socket with address and port, and starts listening. It expects // a valid IPv4 or IPv6 address. Otherwise, it returns ERR_ADDRESS_INVALID. diff --git a/naiveproxy/src/net/socket/socket_test_util.cc b/naiveproxy/src/net/socket/socket_test_util.cc index dc3017b289..21366f033b 100644 --- a/naiveproxy/src/net/socket/socket_test_util.cc +++ b/naiveproxy/src/net/socket/socket_test_util.cc @@ -234,7 +234,6 @@ bool StaticSocketDataHelper::VerifyWriteData(const std::string& data, // This is a success, and the function returns true. std::string expected_data(next_write.data, next_write.data_len); std::string actual_data(data.substr(0, next_write.data_len)); - EXPECT_GE(data.length(), expected_data.length()); if (printer) { EXPECT_TRUE(actual_data == expected_data) << "Actual formatted write data:\n" @@ -1405,7 +1404,7 @@ NextProto MockSSLClientSocket::GetNegotiatedProtocol() const { return data_->next_proto; } -absl::optional +std::optional MockSSLClientSocket::GetPeerApplicationSettings() const { return data_->peer_application_settings; } @@ -1531,6 +1530,7 @@ int MockUDPClientSocket::Read(IOBuffer* buf, if (need_read_data_) { read_data_ = data_->OnRead(); + last_tos_ = read_data_.tos; // ERR_IO_PENDING means that the SocketDataProvider is taking responsibility // to complete the async IO manually later (via OnReadComplete). if (read_data_.result == ERR_IO_PENDING) { @@ -1585,7 +1585,11 @@ int MockUDPClientSocket::SetDoNotFragment() { return OK; } -int MockUDPClientSocket::SetRecvEcn() { +int MockUDPClientSocket::SetRecvTos() { + return OK; +} + +int MockUDPClientSocket::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) { return OK; } @@ -1712,6 +1716,10 @@ void MockUDPClientSocket::ApplySocketTag(const SocketTag& tag) { tag_ = tag; } +DscpAndEcn MockUDPClientSocket::GetLastTos() const { + return TosToDscpAndEcn(last_tos_); +} + void MockUDPClientSocket::OnReadComplete(const MockRead& data) { if (!data_) return; @@ -1725,6 +1733,7 @@ void MockUDPClientSocket::OnReadComplete(const MockRead& data) { DCHECK(need_read_data_); read_data_ = data; + last_tos_ = data.tos; need_read_data_ = false; // The caller is simulating that this IO completes right now. Don't @@ -1944,7 +1953,7 @@ MockTransportClientSocketPool::~MockTransportClientSocketPool() = default; int MockTransportClientSocketPool::RequestSocket( const ClientSocketPool::GroupId& group_id, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, diff --git a/naiveproxy/src/net/socket/socket_test_util.h b/naiveproxy/src/net/socket/socket_test_util.h index 253ca312db..13b39cb91b 100644 --- a/naiveproxy/src/net/socket/socket_test_util.h +++ b/naiveproxy/src/net/socket/socket_test_util.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -42,7 +43,6 @@ #include "net/ssl/ssl_config_service.h" #include "net/ssl/ssl_info.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace base { class RunLoop; @@ -128,7 +128,8 @@ struct MockReadWrite { result(0), data(nullptr), data_len(0), - sequence_number(0) {} + sequence_number(0), + tos(0) {} // Read/write failure (no data). MockReadWrite(IoMode io_mode, int result) @@ -136,7 +137,8 @@ struct MockReadWrite { result(result), data(nullptr), data_len(0), - sequence_number(0) {} + sequence_number(0), + tos(0) {} // Read/write failure (no data), with sequence information. MockReadWrite(IoMode io_mode, int result, int seq) @@ -144,7 +146,8 @@ struct MockReadWrite { result(result), data(nullptr), data_len(0), - sequence_number(seq) {} + sequence_number(seq), + tos(0) {} // Asynchronous read/write success (inferred data length). explicit MockReadWrite(const char* data) @@ -152,7 +155,8 @@ struct MockReadWrite { result(0), data(data), data_len(strlen(data)), - sequence_number(0) {} + sequence_number(0), + tos(0) {} // Read/write success (inferred data length). MockReadWrite(IoMode io_mode, const char* data) @@ -160,7 +164,8 @@ struct MockReadWrite { result(0), data(data), data_len(strlen(data)), - sequence_number(0) {} + sequence_number(0), + tos(0) {} // Read/write success. MockReadWrite(IoMode io_mode, const char* data, int data_len) @@ -168,7 +173,8 @@ struct MockReadWrite { result(0), data(data), data_len(data_len), - sequence_number(0) {} + sequence_number(0), + tos(0) {} // Read/write success (inferred data length) with sequence information. MockReadWrite(IoMode io_mode, int seq, const char* data) @@ -176,7 +182,8 @@ struct MockReadWrite { result(0), data(data), data_len(strlen(data)), - sequence_number(seq) {} + sequence_number(seq), + tos(0) {} // Read/write success with sequence information. MockReadWrite(IoMode io_mode, const char* data, int data_len, int seq) @@ -184,7 +191,21 @@ struct MockReadWrite { result(0), data(data), data_len(data_len), - sequence_number(seq) {} + sequence_number(seq), + tos(0) {} + + // Read/write success with sequence and TOS information. + MockReadWrite(IoMode io_mode, + const char* data, + int data_len, + int seq, + uint8_t tos_byte) + : mode(io_mode), + result(0), + data(data), + data_len(data_len), + sequence_number(seq), + tos(tos_byte) {} IoMode mode; int result; @@ -196,6 +217,9 @@ struct MockReadWrite { // an ERR_IO_PENDING is returned. int sequence_number; // The sequence number at which a read is allowed // to occur. + + // The TOS byte of the datagram, for datagram sockets only. + uint8_t tos; }; typedef MockReadWrite MockRead; @@ -286,7 +310,7 @@ class SocketDataProvider { } bool set_keep_alive_result() const { return set_keep_alive_result_; } - const absl::optional& expected_addresses() const { + const std::optional& expected_addresses() const { return expected_addresses_; } void set_expected_addresses(net::AddressList addresses) { @@ -331,7 +355,7 @@ class SocketDataProvider { int set_send_buffer_size_result_ = net::OK; bool set_no_delay_result_ = true; bool set_keep_alive_result_ = true; - absl::optional expected_addresses_; + std::optional expected_addresses_; }; // The AsyncSocket is an interface used by the SocketDataProvider to @@ -486,7 +510,7 @@ struct SSLSocketDataProvider { NextProto next_proto = kProtoUnknown; // Result for GetPeerApplicationSettings(). - absl::optional peer_application_settings; + std::optional peer_application_settings; // Result for GetSSLInfo(). SSLInfo ssl_info; @@ -497,19 +521,19 @@ struct SSLSocketDataProvider { // Result for GetECHRetryConfigs(). std::vector ech_retry_configs; - absl::optional next_protos_expected_in_ssl_config; - absl::optional expected_application_settings; + std::optional next_protos_expected_in_ssl_config; + std::optional expected_application_settings; uint16_t expected_ssl_version_min; uint16_t expected_ssl_version_max; - absl::optional expected_early_data_enabled; - absl::optional expected_send_client_cert; + std::optional expected_early_data_enabled; + std::optional expected_send_client_cert; scoped_refptr expected_client_cert; - absl::optional expected_host_and_port; - absl::optional expected_ignore_certificate_errors; - absl::optional expected_network_anonymization_key; - absl::optional expected_disable_sha1_server_signatures; - absl::optional> expected_ech_config_list; + std::optional expected_host_and_port; + std::optional expected_ignore_certificate_errors; + std::optional expected_network_anonymization_key; + std::optional expected_disable_sha1_server_signatures; + std::optional> expected_ech_config_list; bool is_connect_data_consumed = false; bool is_confirm_data_consumed = false; @@ -902,7 +926,7 @@ class MockSSLClientSocket : public AsyncSocket, public SSLClientSocket { int GetPeerAddress(IPEndPoint* address) const override; int GetLocalAddress(IPEndPoint* address) const override; NextProto GetNegotiatedProtocol() const override; - absl::optional GetPeerApplicationSettings() const override; + std::optional GetPeerApplicationSettings() const override; bool GetSSLInfo(SSLInfo* ssl_info) override; void GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) const override; @@ -974,7 +998,8 @@ class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket { int SetReceiveBufferSize(int32_t size) override; int SetSendBufferSize(int32_t size) override; int SetDoNotFragment() override; - int SetRecvEcn() override; + int SetRecvTos() override; + int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) override; // DatagramSocket implementation. void Close() override; @@ -999,6 +1024,7 @@ class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket { handles::NetworkHandle GetBoundNetwork() const override; void ApplySocketTag(const SocketTag& tag) override; void SetMsgConfirm(bool confirm) override {} + DscpAndEcn GetLastTos() const override; // AsyncSocket implementation. void OnReadComplete(const MockRead& data) override; @@ -1054,6 +1080,8 @@ class MockUDPClientSocket : public DatagramClientSocket, public AsyncSocket { bool data_transferred_ = false; bool tagged_before_data_transferred_ = true; + uint8_t last_tos_ = 0; + base::WeakPtrFactory weak_factory_{this}; }; @@ -1115,7 +1143,7 @@ class ClientSocketPoolTest { new TestSocketRequest(&request_order_, &completion_count_)); requests_.push_back(base::WrapUnique(request)); int rv = request->handle()->Init( - group_id, socket_params, absl::nullopt /* proxy_annotation_tag */, + group_id, socket_params, std::nullopt /* proxy_annotation_tag */, priority, SocketTag(), respect_limits, request->callback(), ClientSocketPool::ProxyAuthCallback(), socket_pool, NetLogWithSource()); if (rv != ERR_IO_PENDING) @@ -1223,7 +1251,7 @@ class MockTransportClientSocketPool : public TransportClientSocketPool { int RequestSocket( const GroupId& group_id, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, diff --git a/naiveproxy/src/net/socket/socks_connect_job.cc b/naiveproxy/src/net/socket/socks_connect_job.cc index 92c2a710c0..b920c28af2 100644 --- a/naiveproxy/src/net/socket/socks_connect_job.cc +++ b/naiveproxy/src/net/socket/socks_connect_job.cc @@ -203,7 +203,7 @@ int SOCKSConnectJob::DoSOCKSConnectComplete(int result) { return result; } - SetSocket(std::move(socket_), absl::nullopt /* dns_aliases */); + SetSocket(std::move(socket_), std::nullopt /* dns_aliases */); return result; } diff --git a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc index eeb27239bb..236de0c0bb 100644 --- a/naiveproxy/src/net/socket/ssl_client_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_client_socket_impl.cc @@ -547,10 +547,10 @@ NextProto SSLClientSocketImpl::GetNegotiatedProtocol() const { return negotiated_protocol_; } -absl::optional +std::optional SSLClientSocketImpl::GetPeerApplicationSettings() const { if (!SSL_has_application_settings(ssl_.get())) { - return absl::nullopt; + return std::nullopt; } const uint8_t* out_data; @@ -751,7 +751,7 @@ int SSLClientSocketImpl::Init() { if (IsCachingEnabled()) { bssl::UniquePtr session = context_->ssl_client_session_cache()->Lookup( - GetSessionCacheKey(/*dest_ip_addr=*/absl::nullopt)); + GetSessionCacheKey(/*dest_ip_addr=*/std::nullopt)); if (!session) { // If a previous session negotiated an RSA cipher suite then it may have // been inserted into the cache keyed by both hostname and resolved IP @@ -1531,7 +1531,7 @@ void SSLClientSocketImpl::DoPeek() { if (err == ERR_EARLY_DATA_REJECTED || err == ERR_WRONG_VERSION_ON_EARLY_DATA) { context_->ssl_client_session_cache()->ClearEarlyData( - GetSessionCacheKey(absl::nullopt)); + GetSessionCacheKey(std::nullopt)); } handled_early_data_result_ = true; @@ -1654,7 +1654,7 @@ int SSLClientSocketImpl::NewSessionCallback(SSL_SESSION* session) { if (!IsCachingEnabled()) return 0; - absl::optional ip_addr; + std::optional ip_addr; if (SSL_CIPHER_get_kx_nid(SSL_SESSION_get0_cipher(session)) == NID_kx_rsa) { // If RSA key exchange was used, additionally key the cache with the // destination IP address. Of course, if a proxy is being used, the @@ -1675,7 +1675,7 @@ int SSLClientSocketImpl::NewSessionCallback(SSL_SESSION* session) { } SSLClientSessionCache::Key SSLClientSocketImpl::GetSessionCacheKey( - absl::optional dest_ip_addr) const { + std::optional dest_ip_addr) const { SSLClientSessionCache::Key key; key.server = host_and_port_; key.dest_ip_addr = dest_ip_addr; diff --git a/naiveproxy/src/net/socket/ssl_client_socket_impl.h b/naiveproxy/src/net/socket/ssl_client_socket_impl.h index f2ddb4b99b..d67ef97e83 100644 --- a/naiveproxy/src/net/socket/ssl_client_socket_impl.h +++ b/naiveproxy/src/net/socket/ssl_client_socket_impl.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -31,7 +32,6 @@ #include "net/ssl/ssl_client_session_cache.h" #include "net/ssl/ssl_config.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/base.h" #include "third_party/boringssl/src/include/openssl/ssl.h" @@ -91,7 +91,7 @@ class SSLClientSocketImpl : public SSLClientSocket, const NetLogWithSource& NetLog() const override; bool WasEverUsed() const override; NextProto GetNegotiatedProtocol() const override; - absl::optional GetPeerApplicationSettings() const override; + std::optional GetPeerApplicationSettings() const override; bool GetSSLInfo(SSLInfo* ssl_info) override; int64_t GetTotalReceivedBytes() const override; void GetSSLCertRequestInfo( @@ -162,7 +162,7 @@ class SSLClientSocketImpl : public SSLClientSocket, // Returns a session cache key for this socket. SSLClientSessionCache::Key GetSessionCacheKey( - absl::optional dest_ip_addr) const; + std::optional dest_ip_addr) const; // Returns true if renegotiations are allowed. bool IsRenegotiationAllowed() const; diff --git a/naiveproxy/src/net/socket/ssl_connect_job.cc b/naiveproxy/src/net/socket/ssl_connect_job.cc index d09ba3ca42..f80d60d32b 100644 --- a/naiveproxy/src/net/socket/ssl_connect_job.cc +++ b/naiveproxy/src/net/socket/ssl_connect_job.cc @@ -274,7 +274,7 @@ int SSLConnectJob::DoTransportConnect() { next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE; // If this is an ECH retry, connect to the same server as before. - absl::optional + std::optional endpoint_result_override; if (ech_retry_configs_) { DCHECK(ssl_client_context()->config().ech_enabled); @@ -473,7 +473,6 @@ int SSLConnectJob::DoSSLConnectComplete(int result) { return OK; } - const std::string& host = params_->host_and_port().host(); if (is_ech_capable && ech_enabled) { // These values are persisted to logs. Entries should not be renumbered // and numeric values should never be reused. @@ -527,14 +526,6 @@ int SSLConnectJob::DoSSLConnectComplete(int result) { SSLConnectionStatusToVersion(ssl_info.connection_status); UMA_HISTOGRAM_ENUMERATION("Net.SSLVersion", version, SSL_CONNECTION_VERSION_MAX); - if (IsGoogleHost(host)) { - // Google hosts all support TLS 1.2, so any occurrences of TLS 1.0 or TLS - // 1.1 will be from an outdated insecure TLS MITM proxy, such as some - // antivirus configurations. TLS 1.0 and 1.1 are deprecated, so record - // these to see how prevalent they are. See https://crbug.com/896013. - UMA_HISTOGRAM_ENUMERATION("Net.SSLVersionGoogle", version, - SSL_CONNECTION_VERSION_MAX); - } uint16_t cipher_suite = SSLConnectionStatusToCipherSuite(ssl_info.connection_status); diff --git a/naiveproxy/src/net/socket/ssl_connect_job.h b/naiveproxy/src/net/socket/ssl_connect_job.h index 396202d573..fe308b3dbb 100644 --- a/naiveproxy/src/net/socket/ssl_connect_job.h +++ b/naiveproxy/src/net/socket/ssl_connect_job.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -26,7 +27,6 @@ #include "net/socket/ssl_client_socket.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_config_service.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -211,11 +211,11 @@ class NET_EXPORT_PRIVATE SSLConnectJob : public ConnectJob, // The endpoint result used by `nested_connect_job_`. Stored because // `nested_connect_job_` has a limited lifetime. - absl::optional endpoint_result_; + std::optional endpoint_result_; - // If not `absl::nullopt`, the ECH retry configs to use in the ECH recovery + // If not `std::nullopt`, the ECH retry configs to use in the ECH recovery // flow. `endpoint_result_` will then contain the endpoint to reconnect to. - absl::optional> ech_retry_configs_; + std::optional> ech_retry_configs_; }; } // namespace net diff --git a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc index 0c92e261e4..487800f784 100644 --- a/naiveproxy/src/net/socket/ssl_server_socket_impl.cc +++ b/naiveproxy/src/net/socket/ssl_server_socket_impl.cc @@ -5,6 +5,7 @@ #include "net/socket/ssl_server_socket_impl.h" #include +#include #include #include "base/functional/bind.h" @@ -28,7 +29,6 @@ #include "net/ssl/ssl_info.h" #include "net/ssl/ssl_private_key.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/err.h" #include "third_party/boringssl/src/include/openssl/pool.h" @@ -92,7 +92,7 @@ class SSLServerContextImpl::SocketImpl : public SSLServerSocket, const NetLogWithSource& NetLog() const override; bool WasEverUsed() const override; NextProto GetNegotiatedProtocol() const override; - absl::optional GetPeerApplicationSettings() const override; + std::optional GetPeerApplicationSettings() const override; bool GetSSLInfo(SSLInfo* ssl_info) override; int64_t GetTotalReceivedBytes() const override; void ApplySocketTag(const SocketTag& tag) override; @@ -545,10 +545,10 @@ NextProto SSLServerContextImpl::SocketImpl::GetNegotiatedProtocol() const { return negotiated_protocol_; } -absl::optional +std::optional SSLServerContextImpl::SocketImpl::GetPeerApplicationSettings() const { if (!SSL_has_application_settings(ssl_.get())) { - return absl::nullopt; + return std::nullopt; } const uint8_t* out_data; diff --git a/naiveproxy/src/net/socket/stream_socket.cc b/naiveproxy/src/net/socket/stream_socket.cc index a8cf99a120..3b670bce38 100644 --- a/naiveproxy/src/net/socket/stream_socket.cc +++ b/naiveproxy/src/net/socket/stream_socket.cc @@ -13,9 +13,9 @@ void StreamSocket::SetBeforeConnectCallback( NOTREACHED(); } -absl::optional StreamSocket::GetPeerApplicationSettings() +std::optional StreamSocket::GetPeerApplicationSettings() const { - return absl::nullopt; + return std::nullopt; } void StreamSocket::GetSSLCertRequestInfo( diff --git a/naiveproxy/src/net/socket/stream_socket.h b/naiveproxy/src/net/socket/stream_socket.h index c0ffd65751..d5c77c3a9e 100644 --- a/naiveproxy/src/net/socket/stream_socket.h +++ b/naiveproxy/src/net/socket/stream_socket.h @@ -7,13 +7,14 @@ #include +#include + #include "base/functional/bind.h" #include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/dns/public/resolve_error_info.h" #include "net/socket/next_proto.h" #include "net/socket/socket.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -116,7 +117,7 @@ class NET_EXPORT StreamSocket : public Socket { // Get data received from peer in ALPS TLS extension. // Returns a (possibly empty) value if a TLS version supporting ALPS was used // and ALPS was negotiated, nullopt otherwise. - virtual absl::optional GetPeerApplicationSettings() const; + virtual std::optional GetPeerApplicationSettings() const; // Gets the SSL connection information of the socket. Returns false if // SSL was not used by this socket. diff --git a/naiveproxy/src/net/socket/tcp_client_socket.cc b/naiveproxy/src/net/socket/tcp_client_socket.cc index 0f34cd5144..ddae0a24c7 100644 --- a/naiveproxy/src/net/socket/tcp_client_socket.cc +++ b/naiveproxy/src/net/socket/tcp_client_socket.cc @@ -288,7 +288,7 @@ int TCPClientSocket::DoConnect() { int TCPClientSocket::DoConnectComplete(int result) { if (start_connect_attempt_) { EmitConnectAttemptHistograms(result); - start_connect_attempt_ = absl::nullopt; + start_connect_attempt_ = std::nullopt; connect_attempt_timer_.Stop(); } @@ -342,7 +342,7 @@ void TCPClientSocket::Disconnect() { void TCPClientSocket::DoDisconnect() { if (start_connect_attempt_) { EmitConnectAttemptHistograms(ERR_ABORTED); - start_connect_attempt_ = absl::nullopt; + start_connect_attempt_ = std::nullopt; connect_attempt_timer_.Stop(); } @@ -581,7 +581,7 @@ base::TimeDelta TCPClientSocket::GetConnectAttemptTimeout() { if (!base::FeatureList::IsEnabled(features::kTimeoutTcpConnectAttempt)) return base::TimeDelta::Max(); - absl::optional transport_rtt = absl::nullopt; + std::optional transport_rtt = std::nullopt; if (network_quality_estimator_) transport_rtt = network_quality_estimator_->GetTransportRTT(); diff --git a/naiveproxy/src/net/socket/tcp_client_socket.h b/naiveproxy/src/net/socket/tcp_client_socket.h index b5970bc282..5af7de6fc2 100644 --- a/naiveproxy/src/net/socket/tcp_client_socket.h +++ b/naiveproxy/src/net/socket/tcp_client_socket.h @@ -233,7 +233,7 @@ class NET_EXPORT TCPClientSocket : public TransportClientSocket, bool was_disconnected_on_suspend_ = false; // The time when the latest connect attempt was started. - absl::optional start_connect_attempt_; + std::optional start_connect_attempt_; // The NetworkQualityEstimator for the context this socket is associated with. // Can be nullptr. diff --git a/naiveproxy/src/net/socket/tcp_server_socket.cc b/naiveproxy/src/net/socket/tcp_server_socket.cc index ca8044921a..7154fd8e3b 100644 --- a/naiveproxy/src/net/socket/tcp_server_socket.cc +++ b/naiveproxy/src/net/socket/tcp_server_socket.cc @@ -35,7 +35,7 @@ TCPServerSocket::~TCPServerSocket() = default; int TCPServerSocket::Listen(const IPEndPoint& address, int backlog, - absl::optional ipv6_only) { + std::optional ipv6_only) { int result = OK; if (!adopted_opened_socket_) { result = socket_->Open(address.GetFamily()); diff --git a/naiveproxy/src/net/socket/tcp_server_socket.h b/naiveproxy/src/net/socket/tcp_server_socket.h index 7fe176718b..528248e51b 100644 --- a/naiveproxy/src/net/socket/tcp_server_socket.h +++ b/naiveproxy/src/net/socket/tcp_server_socket.h @@ -41,7 +41,7 @@ class NET_EXPORT TCPServerSocket : public ServerSocket { // net::ServerSocket implementation. int Listen(const IPEndPoint& address, int backlog, - absl::optional ipv6_only) override; + std::optional ipv6_only) override; int GetLocalAddress(IPEndPoint* address) const override; int Accept(std::unique_ptr* socket, CompletionOnceCallback callback) override; diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool.cc b/naiveproxy/src/net/socket/transport_client_socket_pool.cc index dd02c27c16..6938c1f149 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool.cc +++ b/naiveproxy/src/net/socket/transport_client_socket_pool.cc @@ -81,7 +81,7 @@ TransportClientSocketPool::Request::Request( RespectLimits respect_limits, Flags flags, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, const NetLogWithSource& net_log) : handle_(handle), callback_(std::move(callback)), @@ -244,7 +244,7 @@ void TransportClientSocketPool::RemoveHigherLayeredPool( int TransportClientSocketPool::RequestSocket( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, @@ -298,7 +298,7 @@ int TransportClientSocketPool::RequestSocket( int TransportClientSocketPool::RequestSockets( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, int num_sockets, CompletionOnceCallback callback, const NetLogWithSource& net_log) { @@ -842,10 +842,9 @@ void TransportClientSocketPool::OnSSLConfigForServersChanged( // If the proxy chain includes a server from `servers` and uses SSL settings // (HTTPS or QUIC), refresh every group. - // TODO(https://crbug.com/1491092): Check each ProxyServer in `proxy_chain_`. bool proxy_matches = false; for (const ProxyServer& proxy_server : proxy_chain_.proxy_servers()) { - if (proxy_server.is_http_like() && !proxy_server.is_http() && + if (proxy_server.is_secure_http_like() && servers.contains(proxy_server.host_port_pair())) { proxy_matches = true; } @@ -912,7 +911,7 @@ bool TransportClientSocketPool::CloseOneIdleConnectionInHigherLayeredPool() { // This pool doesn't have any idle sockets. It's possible that a pool at a // higher layer is holding one of this sockets active, but it's actually idle. // Query the higher layers. - for (auto* higher_pool : higher_pools_) { + for (HigherLayeredPool* higher_pool : higher_pools_) { if (higher_pool->CloseOneIdleConnection()) return true; } @@ -1310,7 +1309,7 @@ void TransportClientSocketPool::OnConnectJobComplete(Group* group, // Check if the ConnectJob is already bound to a Request. If so, result is // returned to that specific request. - absl::optional bound_request = + std::optional bound_request = group->FindAndRemoveBoundRequestForConnectJob(job); Request* request = nullptr; std::unique_ptr owned_request; @@ -1835,7 +1834,7 @@ TransportClientSocketPool::Group::BindRequestToConnectJob( return request; } -absl::optional +std::optional TransportClientSocketPool::Group::FindAndRemoveBoundRequestForConnectJob( ConnectJob* connect_job) { for (auto bound_pair = bound_requests_.begin(); @@ -1846,7 +1845,7 @@ TransportClientSocketPool::Group::FindAndRemoveBoundRequestForConnectJob( bound_requests_.erase(bound_pair); return std::move(ret); } - return absl::nullopt; + return std::nullopt; } std::unique_ptr diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool.h b/naiveproxy/src/net/socket/transport_client_socket_pool.h index bb218b3f07..c9896e5078 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool.h +++ b/naiveproxy/src/net/socket/transport_client_socket_pool.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include "net/socket/socket_tag.h" #include "net/socket/ssl_client_socket.h" #include "net/socket/stream_socket.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -99,7 +99,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool RespectLimits respect_limits, Flags flags, scoped_refptr socket_params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, const NetLogWithSource& net_log); Request(const Request&) = delete; @@ -117,7 +117,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool RespectLimits respect_limits() const { return respect_limits_; } Flags flags() const { return flags_; } SocketParams* socket_params() const { return socket_params_.get(); } - const absl::optional& proxy_annotation_tag() + const std::optional& proxy_annotation_tag() const { return proxy_annotation_tag_; } @@ -141,7 +141,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool const RespectLimits respect_limits_; const Flags flags_; const scoped_refptr socket_params_; - const absl::optional proxy_annotation_tag_; + const std::optional proxy_annotation_tag_; const NetLogWithSource net_log_; const SocketTag socket_tag_; raw_ptr job_ = nullptr; @@ -191,7 +191,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool int RequestSocket( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, @@ -202,7 +202,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool int RequestSockets( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, int num_sockets, CompletionOnceCallback callback, const NetLogWithSource& net_log) override; @@ -429,8 +429,8 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool const Request* BindRequestToConnectJob(ConnectJob* connect_job); // Finds the request, if any, bound to |connect_job|, and returns the - // BoundRequest or absl::nullopt if there was none. - absl::optional FindAndRemoveBoundRequestForConnectJob( + // BoundRequest or std::nullopt if there was none. + std::optional FindAndRemoveBoundRequestForConnectJob( ConnectJob* connect_job); // Finds the bound request, if any, corresponding to |client_socket_handle| @@ -795,7 +795,7 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool // Pools that create connections through |this|. |this| will try to close // their idle sockets when it stalls. Must be empty on destruction. - std::set higher_pools_; + std::set> higher_pools_; const raw_ptr ssl_client_context_; diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.cc b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.cc index c0ff3b00ad..5618150c3a 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.cc +++ b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.cc @@ -342,7 +342,7 @@ void SetIPv6Address(IPEndPoint* address) { MockTransportClientSocketFactory::Rule::Rule( Type type, - absl::optional> expected_addresses, + std::optional> expected_addresses, Error connect_error) : type(type), expected_addresses(std::move(expected_addresses)), diff --git a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h index 535f525f85..58295d3274 100644 --- a/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h +++ b/naiveproxy/src/net/socket/transport_client_socket_pool_test_util.h @@ -10,6 +10,7 @@ #define NET_SOCKET_TRANSPORT_CLIENT_SOCKET_POOL_TEST_UTIL_H_ #include +#include #include #include "base/compiler_specific.h" @@ -23,7 +24,6 @@ #include "net/socket/client_socket_handle.h" #include "net/socket/socket_performance_watcher.h" #include "net/socket/stream_socket.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -76,8 +76,8 @@ class MockTransportClientSocketFactory : public ClientSocketFactory { // A rule describing a mock `TransportClientSocket` to create. struct Rule { explicit Rule(Type type, - absl::optional> expected_addresses = - absl::nullopt, + std::optional> expected_addresses = + std::nullopt, Error connect_error = ERR_CONNECTION_FAILED); ~Rule(); Rule(const Rule&); @@ -86,7 +86,7 @@ class MockTransportClientSocketFactory : public ClientSocketFactory { Type type; // If specified, the addresses that should be passed into // `CreateTransportClientSocket`. - absl::optional> expected_addresses; + std::optional> expected_addresses; // The error to use if `type` specifies a failing connection. Ignored // otherwise. Error connect_error; diff --git a/naiveproxy/src/net/socket/transport_connect_job.cc b/naiveproxy/src/net/socket/transport_connect_job.cc index 501eaa04d8..648cc65abf 100644 --- a/naiveproxy/src/net/socket/transport_connect_job.cc +++ b/naiveproxy/src/net/socket/transport_connect_job.cc @@ -119,7 +119,7 @@ TransportConnectJob::TransportConnectJob( const scoped_refptr& params, Delegate* delegate, const NetLogWithSource* net_log, - absl::optional endpoint_result_override) + std::optional endpoint_result_override) : ConnectJob(priority, socket_tag, ConnectionTimeout(), @@ -183,7 +183,7 @@ ResolveErrorInfo TransportConnectJob::GetResolveErrorInfo() const { return resolve_error_info_; } -absl::optional +std::optional TransportConnectJob::GetHostResolverEndpointResult() const { CHECK_LT(current_endpoint_result_, endpoint_results_.size()); return endpoint_results_[current_endpoint_result_]; diff --git a/naiveproxy/src/net/socket/transport_connect_job.h b/naiveproxy/src/net/socket/transport_connect_job.h index 06000c9fb7..7e091d3ab9 100644 --- a/naiveproxy/src/net/socket/transport_connect_job.h +++ b/naiveproxy/src/net/socket/transport_connect_job.h @@ -6,6 +6,7 @@ #define NET_SOCKET_TRANSPORT_CONNECT_JOB_H_ #include +#include #include #include #include @@ -25,7 +26,6 @@ #include "net/dns/public/secure_dns_policy.h" #include "net/socket/connect_job.h" #include "net/socket/connection_attempts.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "url/scheme_host_port.h" @@ -135,8 +135,8 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob { const scoped_refptr& params, Delegate* delegate, const NetLogWithSource* net_log, - absl::optional - endpoint_result_override = absl::nullopt); + std::optional + endpoint_result_override = std::nullopt); TransportConnectJob(const TransportConnectJob&) = delete; TransportConnectJob& operator=(const TransportConnectJob&) = delete; @@ -148,7 +148,7 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob { bool HasEstablishedConnection() const override; ConnectionAttempts GetConnectionAttempts() const override; ResolveErrorInfo GetResolveErrorInfo() const override; - absl::optional GetHostResolverEndpointResult() + std::optional GetHostResolverEndpointResult() const override; static base::TimeDelta ConnectionTimeout(); diff --git a/naiveproxy/src/net/socket/udp_client_socket.cc b/naiveproxy/src/net/socket/udp_client_socket.cc index 6df3fe1cf2..76a3183831 100644 --- a/naiveproxy/src/net/socket/udp_client_socket.cc +++ b/naiveproxy/src/net/socket/udp_client_socket.cc @@ -219,8 +219,12 @@ int UDPClientSocket::SetDoNotFragment() { return socket_.SetDoNotFragment(); } -int UDPClientSocket::SetRecvEcn() { - return socket_.SetRecvEcn(); +int UDPClientSocket::SetRecvTos() { + return socket_.SetRecvTos(); +} + +int UDPClientSocket::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) { + return socket_.SetTos(dscp, ecn); } void UDPClientSocket::SetMsgConfirm(bool confirm) { @@ -262,4 +266,8 @@ int UDPClientSocket::AdoptOpenedSocket(AddressFamily address_family, return rv; } +DscpAndEcn UDPClientSocket::GetLastTos() const { + return socket_.GetLastTos(); +} + } // namespace net diff --git a/naiveproxy/src/net/socket/udp_client_socket.h b/naiveproxy/src/net/socket/udp_client_socket.h index 503dbd61d3..14c0c00b3b 100644 --- a/naiveproxy/src/net/socket/udp_client_socket.h +++ b/naiveproxy/src/net/socket/udp_client_socket.h @@ -52,6 +52,7 @@ class NET_EXPORT_PRIVATE UDPClientSocket : public DatagramClientSocket { CompletionOnceCallback callback) override; int ConnectUsingDefaultNetworkAsync(const IPEndPoint& address, CompletionOnceCallback callback) override; + DscpAndEcn GetLastTos() const override; handles::NetworkHandle GetBoundNetwork() const override; void ApplySocketTag(const SocketTag& tag) override; @@ -72,7 +73,8 @@ class NET_EXPORT_PRIVATE UDPClientSocket : public DatagramClientSocket { int SetReceiveBufferSize(int32_t size) override; int SetSendBufferSize(int32_t size) override; int SetDoNotFragment() override; - int SetRecvEcn() override; + int SetRecvTos() override; + int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) override; void SetMsgConfirm(bool confirm) override; const NetLogWithSource& NetLog() const override; void EnableRecvOptimization() override; diff --git a/naiveproxy/src/net/socket/udp_server_socket.cc b/naiveproxy/src/net/socket/udp_server_socket.cc index 1520411b2b..0f1968b9d7 100644 --- a/naiveproxy/src/net/socket/udp_server_socket.cc +++ b/naiveproxy/src/net/socket/udp_server_socket.cc @@ -75,8 +75,8 @@ int UDPServerSocket::SetDoNotFragment() { return socket_.SetDoNotFragment(); } -int UDPServerSocket::SetRecvEcn() { - return socket_.SetRecvEcn(); +int UDPServerSocket::SetRecvTos() { + return socket_.SetRecvTos(); } void UDPServerSocket::SetMsgConfirm(bool confirm) { @@ -135,10 +135,18 @@ int UDPServerSocket::SetDiffServCodePoint(DiffServCodePoint dscp) { return socket_.SetDiffServCodePoint(dscp); } +int UDPServerSocket::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) { + return socket_.SetTos(dscp, ecn); +} + void UDPServerSocket::DetachFromThread() { socket_.DetachFromThread(); } +DscpAndEcn UDPServerSocket::GetLastTos() const { + return socket_.GetLastTos(); +} + void UDPServerSocket::UseNonBlockingIO() { #if BUILDFLAG(IS_WIN) socket_.UseNonBlockingIO(); diff --git a/naiveproxy/src/net/socket/udp_server_socket.h b/naiveproxy/src/net/socket/udp_server_socket.h index f93c84afa5..19f223eb53 100644 --- a/naiveproxy/src/net/socket/udp_server_socket.h +++ b/naiveproxy/src/net/socket/udp_server_socket.h @@ -42,7 +42,7 @@ class NET_EXPORT UDPServerSocket : public DatagramServerSocket { int SetReceiveBufferSize(int32_t size) override; int SetSendBufferSize(int32_t size) override; int SetDoNotFragment() override; - int SetRecvEcn() override; + int SetRecvTos() override; void SetMsgConfirm(bool confirm) override; void Close() override; int GetPeerAddress(IPEndPoint* address) const override; @@ -58,7 +58,9 @@ class NET_EXPORT UDPServerSocket : public DatagramServerSocket { int SetMulticastTimeToLive(int time_to_live) override; int SetMulticastLoopbackMode(bool loopback) override; int SetDiffServCodePoint(DiffServCodePoint dscp) override; + int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) override; void DetachFromThread() override; + DscpAndEcn GetLastTos() const override; private: UDPSocket socket_; diff --git a/naiveproxy/src/net/socket/udp_socket_posix.cc b/naiveproxy/src/net/socket/udp_socket_posix.cc index 47f525bcfa..828c0fbf62 100644 --- a/naiveproxy/src/net/socket/udp_socket_posix.cc +++ b/naiveproxy/src/net/socket/udp_socket_posix.cc @@ -570,7 +570,7 @@ int UDPSocketPosix::SetDoNotFragment() { #endif } -int UDPSocketPosix::SetRecvEcn() { +int UDPSocketPosix::SetRecvTos() { DCHECK_NE(socket_, kInvalidSocket); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -754,6 +754,11 @@ void UDPSocketPosix::LogWrite(int result, } } +// TODO(crbug.com/1491628): Because InternalRecvFromConnectedSocket() uses +// recvfrom() instead of recvmsg(), it cannot report received ECN marks for +// QUIC ACK-ECN frames. It might be time to deprecate +// experimental_recv_optimization_enabled_ if that experiment has run its +// course. int UDPSocketPosix::InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address) { @@ -805,11 +810,17 @@ int UDPSocketPosix::InternalRecvFromNonConnectedSocket(IOBuffer* buf, .iov_base = buf->data(), .iov_len = static_cast(buf_len), }; + // control_buffer needs to be big enough to accommodate the maximum + // conceivable number of CMSGs. Other (proprietary) Google QUIC code uses + // 512 Bytes, re-used here. + char control_buffer[512]; struct msghdr msg = { .msg_name = storage.addr, .msg_namelen = storage.addr_len, .msg_iov = &iov, .msg_iovlen = 1, + .msg_control = control_buffer, + .msg_controllen = ABSL_ARRAYSIZE(control_buffer), }; int result; int bytes_transferred = HANDLE_EINTR(recvmsg(socket_, &msg, 0)); @@ -830,6 +841,23 @@ int UDPSocketPosix::InternalRecvFromNonConnectedSocket(IOBuffer* buf, } else { result = bytes_transferred; } + last_tos_ = 0; + if (bytes_transferred > 0 && msg.msg_controllen > 0) { + for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { +#if BUILDFLAG(IS_APPLE) + if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVTOS) || + (cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_TCLASS)) { +#else + if ((cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_TOS) || + (cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_TCLASS)) { +#endif // BUILDFLAG(IS_APPLE) + last_tos_ = *(reinterpret_cast(CMSG_DATA(cmsg))); + } + } + } } LogRead(result, buf->data(), storage.addr_len, storage.addr); @@ -1065,11 +1093,33 @@ int UDPSocketPosix::SetMulticastLoopbackMode(bool loopback) { } int UDPSocketPosix::SetDiffServCodePoint(DiffServCodePoint dscp) { - if (dscp == DSCP_NO_CHANGE) { + return SetTos(dscp, ECN_NO_CHANGE); +} + +int UDPSocketPosix::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) { + if (dscp == DSCP_NO_CHANGE && ecn == ECN_NO_CHANGE) { return OK; } - - int dscp_and_ecn = dscp << 2; + int dscp_and_ecn = (dscp << 2) | ecn; + socklen_t size = sizeof(dscp_and_ecn); + if (dscp == DSCP_NO_CHANGE || ecn == ECN_NO_CHANGE) { + int rv; + if (addr_family_ == AF_INET) { + rv = getsockopt(socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn, &size); + } else { + rv = getsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS, &dscp_and_ecn, &size); + } + if (rv < 0) { + return MapSystemError(errno); + } + if (dscp == DSCP_NO_CHANGE) { + dscp_and_ecn &= ~ECN_LAST; + dscp_and_ecn |= ecn; + } else { + dscp_and_ecn &= ECN_LAST; + dscp_and_ecn |= (dscp << 2); + } + } // Set the IPv4 option in all cases to support dual-stack sockets. int rv = setsockopt(socket_, IPPROTO_IP, IP_TOS, &dscp_and_ecn, sizeof(dscp_and_ecn)); @@ -1081,7 +1131,6 @@ int UDPSocketPosix::SetDiffServCodePoint(DiffServCodePoint dscp) { } if (rv < 0) return MapSystemError(errno); - return OK; } diff --git a/naiveproxy/src/net/socket/udp_socket_posix.h b/naiveproxy/src/net/socket/udp_socket_posix.h index 08a9fc7579..ff9d09e41f 100644 --- a/naiveproxy/src/net/socket/udp_socket_posix.h +++ b/naiveproxy/src/net/socket/udp_socket_posix.h @@ -175,7 +175,7 @@ class NET_EXPORT UDPSocketPosix { // Requests that packets received by this socket have the ECN bit set. Returns // a network error code if there was a problem. - int SetRecvEcn(); + int SetRecvTos(); // If |confirm| is true, then the MSG_CONFIRM flag will be passed to // subsequent writes if it's supported by the platform. @@ -258,6 +258,14 @@ class NET_EXPORT UDPSocketPosix { // Returns a net error code. int SetDiffServCodePoint(DiffServCodePoint dscp); + // Requests that packets sent by this socket have the DSCP and/or ECN + // bits set. Returns a network error code if there was a problem. If + // DSCP_NO_CHANGE or ECN_NO_CHANGE are set, will preserve those parts of + // the original setting. + // ECN values other than ECN_DEFAULT must not be used outside of tests, + // without appropriate congestion control. + int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn); + // Sets IPV6_V6ONLY on the socket. If this flag is true, the socket will be // restricted to only IPv6; false allows both IPv4 and IPv6 traffic. int SetIPv6Only(bool ipv6_only); @@ -295,6 +303,8 @@ class NET_EXPORT UDPSocketPosix { return experimental_recv_optimization_enabled_; } + DscpAndEcn GetLastTos() const { return TosToDscpAndEcn(last_tos_); } + private: enum SocketOptions { SOCKET_OPTION_MULTICAST_LOOP = 1 << 0 @@ -477,6 +487,9 @@ class NET_EXPORT UDPSocketPosix { // UDPSocket is destroyed. OwnedUDPSocketCount owned_socket_count_; + // The last TOS byte received on the socket. + uint8_t last_tos_ = 0; + THREAD_CHECKER(thread_checker_); }; diff --git a/naiveproxy/src/net/socket/udp_socket_win.cc b/naiveproxy/src/net/socket/udp_socket_win.cc index deb0561dbb..20d094fec2 100644 --- a/naiveproxy/src/net/socket/udp_socket_win.cc +++ b/naiveproxy/src/net/socket/udp_socket_win.cc @@ -589,7 +589,7 @@ int UDPSocketWin::SetDoNotFragment() { return rv == 0 ? OK : MapSystemError(WSAGetLastError()); } -int UDPSocketWin::SetRecvEcn() { +int UDPSocketWin::SetRecvTos() { DCHECK_NE(socket_, INVALID_SOCKET); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -1212,6 +1212,11 @@ int UDPSocketWin::SetDiffServCodePoint(DiffServCodePoint dscp) { return OK; } +// TODO(crbug.com/1521435): a stub for future ECN support in Windows. +int UDPSocketWin::SetTos(DiffServCodePoint dscp, EcnCodePoint ecn) { + return SetDiffServCodePoint(dscp); +} + int UDPSocketWin::SetIPv6Only(bool ipv6_only) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (is_connected()) { diff --git a/naiveproxy/src/net/socket/udp_socket_win.h b/naiveproxy/src/net/socket/udp_socket_win.h index 2069bd5301..111a8013c2 100644 --- a/naiveproxy/src/net/socket/udp_socket_win.h +++ b/naiveproxy/src/net/socket/udp_socket_win.h @@ -264,7 +264,7 @@ class NET_EXPORT UDPSocketWin : public base::win::ObjectWatcher::Delegate { // Requests that packets received by this socket have the ECN bit set. Returns // a network error code if there was a problem. - int SetRecvEcn(); + int SetRecvTos(); // This is a no-op on Windows. void SetMsgConfirm(bool confirm); @@ -346,6 +346,14 @@ class NET_EXPORT UDPSocketWin : public base::win::ObjectWatcher::Delegate { // initialization is in progress. int SetDiffServCodePoint(DiffServCodePoint dscp); + // Requests that packets sent by this socket have the DSCP and/or ECN + // bits set. Returns a network error code if there was a problem. If + // DSCP_NO_CHANGE or ECN_NO_CHANGE are set, will preserve those parts of + // the original setting. + // ECN values other than 0 must not be used outside of tests, without + // appropriate congestion control. + int SetTos(DiffServCodePoint dscp, EcnCodePoint ecn); + // Sets IPV6_V6ONLY on the socket. If this flag is true, the socket will be // restricted to only IPv6; false allows both IPv4 and IPv6 traffic. int SetIPv6Only(bool ipv6_only); @@ -372,6 +380,10 @@ class NET_EXPORT UDPSocketWin : public base::win::ObjectWatcher::Delegate { } bool get_use_non_blocking_io_for_testing() { return use_non_blocking_io_; } + // For now, no support for Windows TOS reporting to Quiche + // TODO(crbug.com/1521435): Add windows support for ECN. + DscpAndEcn GetLastTos() const { return {DSCP_DEFAULT, ECN_DEFAULT}; } + private: enum SocketOptions { SOCKET_OPTION_MULTICAST_LOOP = 1 << 0 diff --git a/naiveproxy/src/net/socket/unix_domain_server_socket_posix.cc b/naiveproxy/src/net/socket/unix_domain_server_socket_posix.cc index 10ff174b7a..e27a6cb191 100644 --- a/naiveproxy/src/net/socket/unix_domain_server_socket_posix.cc +++ b/naiveproxy/src/net/socket/unix_domain_server_socket_posix.cc @@ -52,7 +52,7 @@ bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket, int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog, - absl::optional ipv6_only) { + std::optional ipv6_only) { NOTIMPLEMENTED(); return ERR_NOT_IMPLEMENTED; } diff --git a/naiveproxy/src/net/socket/unix_domain_server_socket_posix.h b/naiveproxy/src/net/socket/unix_domain_server_socket_posix.h index b24e377576..2f3ef754c0 100644 --- a/naiveproxy/src/net/socket/unix_domain_server_socket_posix.h +++ b/naiveproxy/src/net/socket/unix_domain_server_socket_posix.h @@ -60,7 +60,7 @@ class NET_EXPORT UnixDomainServerSocket : public ServerSocket { // ServerSocket implementation. int Listen(const IPEndPoint& address, int backlog, - absl::optional ipv6_only) override; + std::optional ipv6_only) override; int ListenWithAddressAndPort(const std::string& address_string, uint16_t port, int backlog) override; diff --git a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc index 56fbcad697..0d233e7a2f 100644 --- a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc +++ b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.cc @@ -64,7 +64,7 @@ void WebSocketTransportClientSocketPool::UnlockEndpoint( int WebSocketTransportClientSocketPool::RequestSocket( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, @@ -129,7 +129,7 @@ int WebSocketTransportClientSocketPool::RequestSocket( int WebSocketTransportClientSocketPool::RequestSockets( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, int num_sockets, CompletionOnceCallback callback, const NetLogWithSource& net_log) { @@ -506,7 +506,7 @@ WebSocketTransportClientSocketPool::ConnectJobDelegate::connect_job_net_log() { WebSocketTransportClientSocketPool::StalledRequest::StalledRequest( const GroupId& group_id, const scoped_refptr& params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, ClientSocketHandle* handle, CompletionOnceCallback callback, diff --git a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h index c32983e541..8c8bb17aac 100644 --- a/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h +++ b/naiveproxy/src/net/socket/websocket_transport_client_socket_pool.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -22,7 +23,6 @@ #include "net/socket/client_socket_pool.h" #include "net/socket/connect_job.h" #include "net/socket/ssl_client_socket.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -65,7 +65,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool int RequestSocket( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, const SocketTag& socket_tag, RespectLimits respect_limits, @@ -76,7 +76,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool int RequestSockets( const GroupId& group_id, scoped_refptr params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, int num_sockets, CompletionOnceCallback callback, const NetLogWithSource& net_log) override; @@ -152,7 +152,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool StalledRequest( const GroupId& group_id, const scoped_refptr& params, - const absl::optional& proxy_annotation_tag, + const std::optional& proxy_annotation_tag, RequestPriority priority, ClientSocketHandle* handle, CompletionOnceCallback callback, @@ -163,7 +163,7 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool const GroupId group_id; const scoped_refptr params; - const absl::optional proxy_annotation_tag; + const std::optional proxy_annotation_tag; const RequestPriority priority; const raw_ptr handle; CompletionOnceCallback callback; diff --git a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc index e2f58b8cd3..243f6a5545 100644 --- a/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc +++ b/naiveproxy/src/net/spdy/bidirectional_stream_spdy_impl.cc @@ -291,7 +291,7 @@ int BidirectionalStreamSpdyImpl::SendRequestHeadersHelper() { http_request_info.method = request_info_->method; http_request_info.extra_headers = request_info_->extra_headers; - CreateSpdyHeadersFromHttpRequest(http_request_info, absl::nullopt, + CreateSpdyHeadersFromHttpRequest(http_request_info, std::nullopt, http_request_info.extra_headers, &headers); written_end_of_stream_ = request_info_->end_stream_on_headers; return stream_->SendRequestHeaders(std::move(headers), diff --git a/naiveproxy/src/net/spdy/http2_priority_dependencies.cc b/naiveproxy/src/net/spdy/http2_priority_dependencies.cc index 60a919f30a..4b2b80c996 100644 --- a/naiveproxy/src/net/spdy/http2_priority_dependencies.cc +++ b/naiveproxy/src/net/spdy/http2_priority_dependencies.cc @@ -36,7 +36,7 @@ void Http2PriorityDependencies::OnStreamCreation( *parent_stream_id = parent->first; } - id_priority_lists_[priority].push_back(std::make_pair(id, priority)); + id_priority_lists_[priority].emplace_back(id, priority); auto it = id_priority_lists_[priority].end(); --it; entry_by_stream_id_[id] = it; @@ -156,7 +156,7 @@ Http2PriorityDependencies::OnStreamUpdate(spdy::SpdyStreamId id, // Move to the new priority. auto old = entry_by_stream_id_.find(id); id_priority_lists_[old->second->second].erase(old->second); - id_priority_lists_[new_priority].push_back(std::make_pair(id, new_priority)); + id_priority_lists_[new_priority].emplace_back(id, new_priority); auto it = id_priority_lists_[new_priority].end(); --it; entry_by_stream_id_[id] = it; diff --git a/naiveproxy/src/net/spdy/spdy_http_utils.cc b/naiveproxy/src/net/spdy/spdy_http_utils.cc index bbe56302e9..7d19befa46 100644 --- a/naiveproxy/src/net/spdy/spdy_http_utils.cc +++ b/naiveproxy/src/net/spdy/spdy_http_utils.cc @@ -161,7 +161,7 @@ SpdyHeadersToHttpResponseHeadersUsingBuilder( // Set-Cookie: bar\0 size_t start = 0; size_t end = 0; - absl::optional location_value; + std::optional location_value; do { end = value.find('\0', start); base::StringPiece tval; @@ -194,7 +194,7 @@ SpdyHeadersToHttpResponseHeadersUsingBuilder( } void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, - absl::optional priority, + std::optional priority, const HttpRequestHeaders& request_headers, spdy::Http2HeaderBlock* headers) { headers->insert({spdy::kHttp2MethodHeader, info.method}); diff --git a/naiveproxy/src/net/spdy/spdy_http_utils.h b/naiveproxy/src/net/spdy/spdy_http_utils.h index 743740e5a2..4702f45b7e 100644 --- a/naiveproxy/src/net/spdy/spdy_http_utils.h +++ b/naiveproxy/src/net/spdy/spdy_http_utils.h @@ -5,6 +5,8 @@ #ifndef NET_SPDY_SPDY_HTTP_UTILS_H_ #define NET_SPDY_SPDY_HTTP_UTILS_H_ +#include + #include "base/memory/ref_counted.h" #include "base/types/expected.h" #include "net/base/net_export.h" @@ -12,7 +14,6 @@ #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -57,7 +58,7 @@ SpdyHeadersToHttpResponseHeadersUsingBuilder( // HttpRequestHeaders. NET_EXPORT void CreateSpdyHeadersFromHttpRequest( const HttpRequestInfo& info, - absl::optional priority, + std::optional priority, const HttpRequestHeaders& request_headers, spdy::Http2HeaderBlock* headers); diff --git a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc index b82b20b241..b241db0537 100644 --- a/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc +++ b/naiveproxy/src/net/spdy/spdy_proxy_client_socket.cc @@ -404,7 +404,7 @@ int SpdyProxyClientSocket::DoSendRequest() { request_line, &request_.extra_headers); spdy::Http2HeaderBlock headers; - CreateSpdyHeadersFromHttpRequest(request_, absl::nullopt, + CreateSpdyHeadersFromHttpRequest(request_, std::nullopt, request_.extra_headers, &headers); return spdy_stream_->SendRequestHeaders(std::move(headers), diff --git a/naiveproxy/src/net/spdy/spdy_session.cc b/naiveproxy/src/net/spdy/spdy_session.cc index 22070e60d4..83bd932718 100644 --- a/naiveproxy/src/net/spdy/spdy_session.cc +++ b/naiveproxy/src/net/spdy/spdy_session.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -731,8 +732,8 @@ void SpdyStreamRequest::OnConfirmHandshakeComplete(int rv) { bool SpdySession::CanPool(TransportSecurityState* transport_security_state, const SSLInfo& ssl_info, const SSLConfigService& ssl_config_service, - const std::string& old_hostname, - const std::string& new_hostname) { + std::string_view old_hostname, + std::string_view new_hostname) { // Pooling is prohibited if the server cert is not valid for the new domain, // and for connections on which client certs were sent. It is also prohibited // when channel ID was sent if the hosts are from different eTLDs+1. @@ -786,7 +787,7 @@ SpdySession::SpdySession( int session_max_queued_capped_frames, const spdy::SettingsMap& initial_settings, bool enable_http2_settings_grease, - const absl::optional& + const std::optional& greased_http2_frame, bool http2_end_stream_with_data_frame, bool enable_priority_update, @@ -937,8 +938,8 @@ int SpdySession::ParseAlps() { continue; } has_valid_entry = true; - accept_ch_entries_received_via_alps_.insert( - std::make_pair(std::move(scheme_host_port), entry.value)); + accept_ch_entries_received_via_alps_.emplace(std::move(scheme_host_port), + entry.value); net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_RECV_ACCEPT_CH, [&] { return NetLogSpdyRecvAcceptChParams(entry); }); @@ -963,7 +964,7 @@ int SpdySession::ParseAlps() { return OK; } -bool SpdySession::VerifyDomainAuthentication(const std::string& domain) const { +bool SpdySession::VerifyDomainAuthentication(std::string_view domain) const { if (availability_state_ == STATE_DRAINING) return false; @@ -1506,10 +1507,11 @@ bool SpdySession::ChangeSocketTag(const SocketTag& new_tag) { socket_->ApplySocketTag(new_tag); SpdySessionKey new_key( - spdy_session_key_.host_port_pair(), spdy_session_key_.proxy_chain(), - spdy_session_key_.privacy_mode(), spdy_session_key_.is_proxy_session(), + spdy_session_key_.host_port_pair(), spdy_session_key_.privacy_mode(), + spdy_session_key_.proxy_chain(), spdy_session_key_.session_usage(), new_tag, spdy_session_key_.network_anonymization_key(), - spdy_session_key_.secure_dns_policy()); + spdy_session_key_.secure_dns_policy(), + spdy_session_key_.disable_cert_verification_network_fetches()); spdy_session_key_ = new_key; return true; @@ -2164,7 +2166,7 @@ void SpdySession::SendInitialData() { static_cast(std::numeric_limits::max()) + 1); // Let insertion silently fail if `settings_map` already contains // `greased_id`. - settings_map.insert(std::make_pair(greased_id, greased_value)); + settings_map.emplace(greased_id, greased_value); } net_log_.AddEvent(NetLogEventType::HTTP2_SESSION_SEND_SETTINGS, [&] { return NetLogSpdySendSettingsParams(&settings_map); @@ -2308,7 +2310,7 @@ void SpdySession::UpdateStreamsSendWindowSize(int32_t delta_window_size) { } } - for (auto* const stream : created_streams_) { + for (SpdyStream* const stream : created_streams_) { if (!stream->AdjustSendWindowSize(delta_window_size)) { DoDrainSession( ERR_HTTP2_FLOW_CONTROL_ERROR, @@ -2506,7 +2508,7 @@ void SpdySession::InsertActivatedStream(std::unique_ptr stream) { spdy::SpdyStreamId stream_id = stream->stream_id(); CHECK_NE(stream_id, 0u); std::pair result = - active_streams_.insert(std::make_pair(stream_id, stream.get())); + active_streams_.emplace(stream_id, stream.get()); CHECK(result.second); std::ignore = stream.release(); } @@ -3023,10 +3025,11 @@ void SpdySession::OnAltSvc( if (!gurl.SchemeIs(url::kHttpsScheme)) return; SSLInfo ssl_info; - if (!GetSSLInfo(&ssl_info)) + if (!GetSSLInfo(&ssl_info)) { return; + } if (!CanPool(transport_security_state_, ssl_info, *ssl_config_service_, - host_port_pair().host(), gurl.host())) { + host_port_pair().host(), gurl.host_piece())) { return; } scheme_host_port = url::SchemeHostPort(gurl); diff --git a/naiveproxy/src/net/spdy/spdy_session.h b/naiveproxy/src/net/spdy/spdy_session.h index 0637fd922c..f4d5c8a8b0 100644 --- a/naiveproxy/src/net/spdy/spdy_session.h +++ b/naiveproxy/src/net/spdy/spdy_session.h @@ -10,8 +10,10 @@ #include #include +#include #include #include +#include #include #include "base/containers/circular_deque.h" @@ -53,7 +55,6 @@ #include "net/third_party/quiche/src/quiche/spdy/core/spdy_framer.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" #include "url/scheme_host_port.h" @@ -318,8 +319,8 @@ class NET_EXPORT SpdySession static bool CanPool(TransportSecurityState* transport_security_state, const SSLInfo& ssl_info, const SSLConfigService& ssl_config_service, - const std::string& old_hostname, - const std::string& new_hostname); + std::string_view old_hostname, + std::string_view new_hostname); // Create a new SpdySession. // |spdy_session_key| is the host/port that this session connects to, privacy @@ -338,7 +339,7 @@ class NET_EXPORT SpdySession int session_max_queued_capped_frames, const spdy::SettingsMap& initial_settings, bool enable_http2_settings_grease, - const absl::optional& + const std::optional& greased_http2_frame, bool http2_end_stream_with_data_frame, bool enable_priority_update, @@ -391,7 +392,7 @@ class NET_EXPORT SpdySession // TODO(wtc): rename this function and the Net.SpdyIPPoolDomainMatch // histogram because this function does more than verifying domain // authentication now. - bool VerifyDomainAuthentication(const std::string& domain) const; + bool VerifyDomainAuthentication(std::string_view domain) const; // Pushes the given producer into the write queue for // |stream|. |stream| is guaranteed to be activated before the @@ -626,7 +627,7 @@ class NET_EXPORT SpdySession using PendingStreamRequestQueue = base::circular_deque>; using ActiveStreamMap = std::map; - using CreatedStreamSet = std::set; + using CreatedStreamSet = std::set>; enum AvailabilityState { // The session is available in its socket pool and can be used @@ -1109,7 +1110,7 @@ class NET_EXPORT SpdySession // If set, an HTTP/2 frame with a reserved frame type will be sent after // every HTTP/2 SETTINGS frame and before every HTTP/2 DATA frame. See // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00. - const absl::optional greased_http2_frame_; + const std::optional greased_http2_frame_; // If set, the HEADERS frame carrying a request without body will not have the // END_STREAM flag set. The stream will be closed by a subsequent empty DATA diff --git a/naiveproxy/src/net/spdy/spdy_session_key.cc b/naiveproxy/src/net/spdy/spdy_session_key.cc index 5ac8b94d82..f60d71bd16 100644 --- a/naiveproxy/src/net/spdy/spdy_session_key.cc +++ b/naiveproxy/src/net/spdy/spdy_session_key.cc @@ -4,6 +4,7 @@ #include "net/spdy/spdy_session_key.h" +#include #include #include "base/feature_list.h" @@ -13,8 +14,8 @@ #include "net/base/host_port_pair.h" #include "net/base/proxy_chain.h" #include "net/base/proxy_string_util.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -22,23 +23,30 @@ SpdySessionKey::SpdySessionKey() = default; SpdySessionKey::SpdySessionKey( const HostPortPair& host_port_pair, - const ProxyChain& proxy_chain, PrivacyMode privacy_mode, - IsProxySession is_proxy_session, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, - SecureDnsPolicy secure_dns_policy) + SecureDnsPolicy secure_dns_policy, + bool disable_cert_verification_network_fetches) : host_port_proxy_pair_(host_port_pair, proxy_chain), privacy_mode_(privacy_mode), - is_proxy_session_(is_proxy_session), + session_usage_(session_usage), socket_tag_(socket_tag), network_anonymization_key_( NetworkAnonymizationKey::IsPartitioningEnabled() ? network_anonymization_key : NetworkAnonymizationKey()), - secure_dns_policy_(secure_dns_policy) { + secure_dns_policy_(secure_dns_policy), + disable_cert_verification_network_fetches_( + disable_cert_verification_network_fetches) { DVLOG(1) << "SpdySessionKey(host=" << host_port_pair.ToString() << ", proxy_chain=" << proxy_chain << ", privacy=" << privacy_mode; + DCHECK(disable_cert_verification_network_fetches_ || + session_usage_ != SessionUsage::kProxy); + DCHECK(privacy_mode_ == PRIVACY_MODE_DISABLED || + session_usage_ != SessionUsage::kProxy); } SpdySessionKey::SpdySessionKey(const SpdySessionKey& other) = default; @@ -47,11 +55,13 @@ SpdySessionKey::~SpdySessionKey() = default; bool SpdySessionKey::operator<(const SpdySessionKey& other) const { return std::tie(privacy_mode_, host_port_proxy_pair_.first, - host_port_proxy_pair_.second, is_proxy_session_, - network_anonymization_key_, secure_dns_policy_, socket_tag_) < + host_port_proxy_pair_.second, session_usage_, + network_anonymization_key_, secure_dns_policy_, + disable_cert_verification_network_fetches_, socket_tag_) < std::tie(other.privacy_mode_, other.host_port_proxy_pair_.first, - other.host_port_proxy_pair_.second, other.is_proxy_session_, + other.host_port_proxy_pair_.second, other.session_usage_, other.network_anonymization_key_, other.secure_dns_policy_, + other.disable_cert_verification_network_fetches_, other.socket_tag_); } @@ -60,9 +70,11 @@ bool SpdySessionKey::operator==(const SpdySessionKey& other) const { host_port_proxy_pair_.first.Equals( other.host_port_proxy_pair_.first) && host_port_proxy_pair_.second == other.host_port_proxy_pair_.second && - is_proxy_session_ == other.is_proxy_session_ && + session_usage_ == other.session_usage_ && network_anonymization_key_ == other.network_anonymization_key_ && secure_dns_policy_ == other.secure_dns_policy_ && + disable_cert_verification_network_fetches_ == + other.disable_cert_verification_network_fetches_ && socket_tag_ == other.socket_tag_; } @@ -76,9 +88,11 @@ SpdySessionKey::CompareForAliasingResult SpdySessionKey::CompareForAliasing( result.is_potentially_aliasable = (privacy_mode_ == other.privacy_mode_ && host_port_proxy_pair_.second == other.host_port_proxy_pair_.second && - is_proxy_session_ == other.is_proxy_session_ && + session_usage_ == other.session_usage_ && network_anonymization_key_ == other.network_anonymization_key_ && - secure_dns_policy_ == other.secure_dns_policy_); + secure_dns_policy_ == other.secure_dns_policy_ && + disable_cert_verification_network_fetches_ == + other.disable_cert_verification_network_fetches_); result.is_socket_tag_match = (socket_tag_ == other.socket_tag_); return result; } diff --git a/naiveproxy/src/net/spdy/spdy_session_key.h b/naiveproxy/src/net/spdy/spdy_session_key.h index f4312161bd..9983c9b59c 100644 --- a/naiveproxy/src/net/spdy/spdy_session_key.h +++ b/naiveproxy/src/net/spdy/spdy_session_key.h @@ -5,39 +5,36 @@ #ifndef NET_SPDY_SPDY_SESSION_KEY_H_ #define NET_SPDY_SPDY_SESSION_KEY_H_ +#include + #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" #include "net/base/network_isolation_key.h" #include "net/base/privacy_mode.h" #include "net/base/proxy_chain.h" +#include "net/base/session_usage.h" #include "net/dns/public/secure_dns_policy.h" #include "net/socket/socket_tag.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { // SpdySessionKey is used as unique index for SpdySessionPool. class NET_EXPORT_PRIVATE SpdySessionKey { public: - enum class IsProxySession { - kFalse, - // This means this is a ProxyServer::Direct() session for an HTTP2 proxy, - // with |host_port_pair| being the proxy host and port. This should not be - // confused with a tunnel over an HTTP2 proxy session, for which - // |proxy_chain| will be information about the proxy being used, and - // |host_port_pair| will be information not about the proxy, but the host - // that we're proxying the connection to. - kTrue, - }; - SpdySessionKey(); + // Note that if `session_usage` is kProxy, then: + // * `privacy_mode` must be PRIVACY_MODE_DISABLED to pool credentialed and + // uncredetialed requests onto the same proxy connections. + // * `disable_cert_verification_network_fetches` must be true, to avoid + // depending on cert fetches, which would be made through the proxy. SpdySessionKey(const HostPortPair& host_port_pair, - const ProxyChain& proxy_chain, PrivacyMode privacy_mode, - IsProxySession is_proxy_session, + const ProxyChain& proxy_chain, + SessionUsage session_usage, const SocketTag& socket_tag, const NetworkAnonymizationKey& network_anonymization_key, - SecureDnsPolicy secure_dns_policy); + SecureDnsPolicy secure_dns_policy, + bool disable_cert_verification_network_fetches); SpdySessionKey(const SpdySessionKey& other); @@ -84,7 +81,7 @@ class NET_EXPORT_PRIVATE SpdySessionKey { return privacy_mode_; } - IsProxySession is_proxy_session() const { return is_proxy_session_; } + SessionUsage session_usage() const { return session_usage_; } const SocketTag& socket_tag() const { return socket_tag_; } @@ -94,16 +91,21 @@ class NET_EXPORT_PRIVATE SpdySessionKey { SecureDnsPolicy secure_dns_policy() const { return secure_dns_policy_; } + bool disable_cert_verification_network_fetches() const { + return disable_cert_verification_network_fetches_; + } + private: HostPortProxyPair host_port_proxy_pair_; // If enabled, then session cannot be tracked by the server. PrivacyMode privacy_mode_ = PRIVACY_MODE_DISABLED; - IsProxySession is_proxy_session_; + SessionUsage session_usage_; SocketTag socket_tag_; // Used to separate requests made in different contexts. If network state // partitioning is disabled this will be set to an empty key. NetworkAnonymizationKey network_anonymization_key_; SecureDnsPolicy secure_dns_policy_; + bool disable_cert_verification_network_fetches_; }; } // namespace net diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.cc b/naiveproxy/src/net/spdy/spdy_session_pool.cc index 23c31f1649..c08c0dd2cd 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.cc +++ b/naiveproxy/src/net/spdy/spdy_session_pool.cc @@ -85,7 +85,7 @@ SpdySessionPool::SpdySessionPool( int session_max_queued_capped_frames, const spdy::SettingsMap& initial_settings, bool enable_http2_settings_grease, - const absl::optional& greased_http2_frame, + const std::optional& greased_http2_frame, bool http2_end_stream_with_data_frame, bool enable_priority_update, bool go_away_on_ip_change, @@ -344,11 +344,11 @@ OnHostResolutionCallbackResult SpdySessionPool::OnHostResolutionComplete( // If socket tags differ, see if session's socket tag can be changed. if (!compare_result.is_socket_tag_match) { SpdySessionKey old_key = available_session->spdy_session_key(); - SpdySessionKey new_key(old_key.host_port_pair(), - old_key.proxy_chain(), old_key.privacy_mode(), - old_key.is_proxy_session(), key.socket_tag(), - old_key.network_anonymization_key(), - old_key.secure_dns_policy()); + SpdySessionKey new_key( + old_key.host_port_pair(), old_key.privacy_mode(), + old_key.proxy_chain(), old_key.session_usage(), key.socket_tag(), + old_key.network_anonymization_key(), old_key.secure_dns_policy(), + old_key.disable_cert_verification_network_fetches()); // If there is already a session with |new_key|, skip this one. // It will be found in |aliases_| in a future iteration. @@ -393,9 +393,10 @@ OnHostResolutionCallbackResult SpdySessionPool::OnHostResolutionComplete( GetDnsAliasesForSessionKey(*it); UnmapKey(*it); SpdySessionKey new_pool_alias_key = SpdySessionKey( - it->host_port_pair(), it->proxy_chain(), it->privacy_mode(), - it->is_proxy_session(), key.socket_tag(), - it->network_anonymization_key(), it->secure_dns_policy()); + it->host_port_pair(), it->privacy_mode(), it->proxy_chain(), + it->session_usage(), key.socket_tag(), + it->network_anonymization_key(), it->secure_dns_policy(), + it->disable_cert_verification_network_fetches()); MapKeyToAvailableSession(new_pool_alias_key, available_session, std::move(pooled_alias_old_dns_aliases)); auto old_it = it; @@ -621,7 +622,7 @@ void SpdySessionPool::MapKeyToAvailableSession( std::set dns_aliases) { DCHECK(base::Contains(sessions_, session.get())); std::pair result = - available_sessions_.insert(std::make_pair(key, session)); + available_sessions_.emplace(key, session); CHECK(result.second); dns_aliases_by_session_key_[key] = std::move(dns_aliases); @@ -656,7 +657,7 @@ void SpdySessionPool::RemoveAliases(const SpdySessionKey& key) { SpdySessionPool::WeakSessionList SpdySessionPool::GetCurrentSessions() const { WeakSessionList current_sessions; - for (auto* session : sessions_) { + for (SpdySession* session : sessions_) { current_sessions.push_back(session->GetWeakPtr()); } return current_sessions; diff --git a/naiveproxy/src/net/spdy/spdy_session_pool.h b/naiveproxy/src/net/spdy/spdy_session_pool.h index 546109c1c5..aab78a7141 100644 --- a/naiveproxy/src/net/spdy/spdy_session_pool.h +++ b/naiveproxy/src/net/spdy/spdy_session_pool.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include "net/ssl/ssl_config_service.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_protocol.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -138,7 +138,7 @@ class NET_EXPORT SpdySessionPool int session_max_queued_capped_frames, const spdy::SettingsMap& initial_settings, bool enable_http2_settings_grease, - const absl::optional& greased_http2_frame, + const std::optional& greased_http2_frame, bool http2_end_stream_with_data_frame, bool enable_priority_update, bool go_away_on_ip_change, @@ -320,14 +320,14 @@ class NET_EXPORT SpdySessionPool private: friend class SpdySessionPoolPeer; // For testing. - using SessionSet = std::set; + using SessionSet = std::set>; using WeakSessionList = std::vector>; using AvailableSessionMap = std::map>; using AliasMap = std::multimap; using DnsAliasesBySessionKeyMap = std::map>; - using RequestSet = std::set; + using RequestSet = std::set>; struct RequestInfoForKey { RequestInfoForKey(); @@ -464,7 +464,7 @@ class NET_EXPORT SpdySessionPool // If set, an HTTP/2 frame with a reserved frame type will be sent after // every HTTP/2 SETTINGS frame and before every HTTP/2 DATA frame. See // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00. - const absl::optional greased_http2_frame_; + const std::optional greased_http2_frame_; // If set, the HEADERS frame carrying a request without body will not have the // END_STREAM flag set. The stream will be closed by a subsequent empty DATA diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.cc b/naiveproxy/src/net/spdy/spdy_test_util_common.cc index 0f2d5464fb..6c04ee4b75 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.cc +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.cc @@ -5,6 +5,7 @@ #include "net/spdy/spdy_test_util_common.h" #include +#include #include #include "base/base64.h" @@ -52,7 +53,6 @@ #include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_test_util.h" #include "testing/gmock/include/gmock/gmock.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/scheme_host_port.h" #include "url/url_constants.h" @@ -441,12 +441,9 @@ base::WeakPtr CreateSpdySessionHelper( auto connection = std::make_unique(); TestCompletionCallback callback; - auto ssl_config = std::make_unique(); - ssl_config->alpn_protos = http_session->GetAlpnProtos(); - ssl_config->application_settings = http_session->GetApplicationSettings(); scoped_refptr socket_params = base::MakeRefCounted( - /*ssl_config_for_origin=*/std::move(ssl_config)); + /*allowed_bad_certs=*/std::vector()); int rv = connection->Init( ClientSocketPool::GroupId( url::SchemeHostPort(url::kHttpsScheme, @@ -454,7 +451,7 @@ base::WeakPtr CreateSpdySessionHelper( key.host_port_pair().port()), key.privacy_mode(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, /*disable_cert_network_fetches=*/false), - socket_params, /*proxy_annotation_tag=*/absl::nullopt, MEDIUM, + socket_params, /*proxy_annotation_tag=*/std::nullopt, MEDIUM, key.socket_tag(), ClientSocketPool::RespectLimits::ENABLED, callback.callback(), ClientSocketPool::ProxyAuthCallback(), http_session->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL, @@ -742,7 +739,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet( spdy::SpdyStreamId stream_id, RequestPriority request_priority, bool priority_incremental, - absl::optional header_request_priority) { + std::optional header_request_priority) { spdy::Http2HeaderBlock block(ConstructGetHeaderBlock(url)); return ConstructSpdyHeaders(stream_id, std::move(block), request_priority, true, priority_incremental, @@ -755,7 +752,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet( int stream_id, RequestPriority request_priority, bool priority_incremental, - absl::optional header_request_priority) { + std::optional header_request_priority) { spdy::Http2HeaderBlock block; block[spdy::kHttp2MethodHeader] = "GET"; AddUrlToHeaderBlock(default_url_.spec(), &block); @@ -804,7 +801,7 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyHeaders( RequestPriority priority, bool fin, bool priority_incremental, - absl::optional header_request_priority) { + std::optional header_request_priority) { // Get the stream id of the next highest priority request // (most recent request of the same priority, or last request of // an earlier priority). diff --git a/naiveproxy/src/net/spdy/spdy_test_util_common.h b/naiveproxy/src/net/spdy/spdy_test_util_common.h index 80f1e2712b..1c8db60786 100644 --- a/naiveproxy/src/net/spdy/spdy_test_util_common.h +++ b/naiveproxy/src/net/spdy/spdy_test_util_common.h @@ -206,7 +206,7 @@ struct SpdySessionDependencies { SpdySession::TimeFunc time_func; bool enable_http2_alternative_service = false; bool enable_http2_settings_grease = false; - absl::optional greased_http2_frame; + std::optional greased_http2_frame; bool http2_end_stream_with_data_frame = false; raw_ptr net_log = nullptr; bool disable_idle_sockets_close_on_memory_pressure = false; @@ -344,7 +344,7 @@ class SpdyTestUtil { spdy::SpdyStreamId stream_id, RequestPriority request_priority, bool priority_incremental = kDefaultPriorityIncremental, - absl::optional header_request_priority = absl::nullopt); + std::optional header_request_priority = std::nullopt); // Constructs a standard SPDY GET HEADERS frame with header compression. // |extra_headers| are the extra header-value pairs, which typically @@ -356,7 +356,7 @@ class SpdyTestUtil { int stream_id, RequestPriority request_priority, bool priority_incremental = kDefaultPriorityIncremental, - absl::optional header_request_priority = absl::nullopt); + std::optional header_request_priority = std::nullopt); // Constructs a SPDY HEADERS frame for a CONNECT request. spdy::SpdySerializedFrame ConstructSpdyConnect( @@ -386,7 +386,7 @@ class SpdyTestUtil { RequestPriority priority, bool fin, bool priority_incremental = kDefaultPriorityIncremental, - absl::optional header_request_priority = absl::nullopt); + std::optional header_request_priority = std::nullopt); // Construct a reply HEADERS frame carrying exactly the given headers and the // default priority. diff --git a/naiveproxy/src/net/ssl/ssl_client_auth_cache.cc b/naiveproxy/src/net/ssl/ssl_client_auth_cache.cc index daa91cc786..63dd2d7b27 100644 --- a/naiveproxy/src/net/ssl/ssl_client_auth_cache.cc +++ b/naiveproxy/src/net/ssl/ssl_client_auth_cache.cc @@ -31,8 +31,7 @@ bool SSLClientAuthCache::Lookup(const HostPortPair& server, void SSLClientAuthCache::Add(const HostPortPair& server, scoped_refptr certificate, scoped_refptr private_key) { - cache_[server] = - std::make_pair(std::move(certificate), std::move(private_key)); + cache_[server] = std::pair(std::move(certificate), std::move(private_key)); // TODO(wtc): enforce a maximum number of entries. } diff --git a/naiveproxy/src/net/ssl/ssl_client_session_cache.h b/naiveproxy/src/net/ssl/ssl_client_session_cache.h index 0ff0054bd4..f8444ac2dd 100644 --- a/naiveproxy/src/net/ssl/ssl_client_session_cache.h +++ b/naiveproxy/src/net/ssl/ssl_client_session_cache.h @@ -9,6 +9,7 @@ #include #include +#include #include #include "base/containers/flat_set.h" @@ -21,7 +22,6 @@ #include "net/base/net_export.h" #include "net/base/network_anonymization_key.h" #include "net/base/privacy_mode.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/base.h" namespace base { @@ -51,7 +51,7 @@ class NET_EXPORT SSLClientSessionCache { bool operator<(const Key& other) const; HostPortPair server; - absl::optional dest_ip_addr; + std::optional dest_ip_addr; NetworkAnonymizationKey network_anonymization_key; PrivacyMode privacy_mode = PRIVACY_MODE_DISABLED; bool disable_legacy_crypto = false; diff --git a/naiveproxy/src/net/ssl/ssl_config.h b/naiveproxy/src/net/ssl/ssl_config.h index eb06bde4f4..62563d999b 100644 --- a/naiveproxy/src/net/ssl/ssl_config.h +++ b/naiveproxy/src/net/ssl/ssl_config.h @@ -7,6 +7,8 @@ #include +#include + #include "base/containers/flat_map.h" #include "base/memory/scoped_refptr.h" #include "net/base/net_export.h" @@ -15,7 +17,6 @@ #include "net/cert/cert_status_flags.h" #include "net/cert/x509_certificate.h" #include "net/socket/next_proto.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -53,8 +54,8 @@ struct NET_EXPORT SSLConfig { // If specified, the minimum and maximum protocol versions that are enabled. // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.) If // unspecified, values from the SSLConfigService are used. - absl::optional version_min_override; - absl::optional version_max_override; + std::optional version_min_override; + std::optional version_max_override; // Whether early data is enabled on this connection. Note that early data has // weaker security properties than normal data and changes the diff --git a/naiveproxy/src/net/ssl/ssl_config_service.h b/naiveproxy/src/net/ssl/ssl_config_service.h index 44f3709ab6..6e9f76a6cc 100644 --- a/naiveproxy/src/net/ssl/ssl_config_service.h +++ b/naiveproxy/src/net/ssl/ssl_config_service.h @@ -5,12 +5,13 @@ #ifndef NET_SSL_SSL_CONFIG_SERVICE_H_ #define NET_SSL_SSL_CONFIG_SERVICE_H_ +#include +#include #include #include "base/observer_list.h" #include "net/base/net_export.h" #include "net/ssl/ssl_config.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -48,27 +49,27 @@ struct NET_EXPORT SSLContextConfig { std::vector disabled_cipher_suites; // If specified, controls whether post-quantum key agreement in TLS - // connections is allowed. If `absl::nullopt`, this is determined by feature + // connections is allowed. If `std::nullopt`, this is determined by feature // flags. - absl::optional post_quantum_override; + std::optional post_quantum_override; // Controls whether ECH is enabled. bool ech_enabled = true; // If specified, controls whether insecure hashes are allowed in TLS - // handshakes. If `absl::nullopt`, this is determined by feature flags. - absl::optional insecure_hash_override; + // handshakes. If `std::nullopt`, this is determined by feature flags. + std::optional insecure_hash_override; // If specified, controls whether the X.509 keyUsage extension is checked in // TLS 1.2 for RSA certificates that chain to a local trust anchor. If - // `absl::nullopt`, this is determined by feature flags. + // `std::nullopt`, this is determined by feature flags. // // Independent of the setting of this value, keyUsage is always checked at TLS // 1.3, for ECDSA certificates, and for all certificates that chain to a known // root. // // TODO(crbug.com/795089): Enable this unconditionally. - absl::optional rsa_key_usage_for_local_anchors_override; + std::optional rsa_key_usage_for_local_anchors_override; }; // The interface for retrieving global SSL configuration. This interface @@ -117,7 +118,7 @@ class NET_EXPORT SSLConfigService { // removed in a future release. Please leave a comment on // https://crbug.com/855690 if you believe this is needed. virtual bool CanShareConnectionWithClientCerts( - const std::string& hostname) const = 0; + std::string_view hostname) const = 0; // Add an observer of this service. void AddObserver(Observer* observer); diff --git a/naiveproxy/src/net/ssl/ssl_config_service_defaults.cc b/naiveproxy/src/net/ssl/ssl_config_service_defaults.cc index c48064549c..7d137e5966 100644 --- a/naiveproxy/src/net/ssl/ssl_config_service_defaults.cc +++ b/naiveproxy/src/net/ssl/ssl_config_service_defaults.cc @@ -14,7 +14,7 @@ SSLContextConfig SSLConfigServiceDefaults::GetSSLContextConfig() { } bool SSLConfigServiceDefaults::CanShareConnectionWithClientCerts( - const std::string& hostname) const { + std::string_view hostname) const { return false; } diff --git a/naiveproxy/src/net/ssl/ssl_config_service_defaults.h b/naiveproxy/src/net/ssl/ssl_config_service_defaults.h index 4bf47d05b5..32770a45d4 100644 --- a/naiveproxy/src/net/ssl/ssl_config_service_defaults.h +++ b/naiveproxy/src/net/ssl/ssl_config_service_defaults.h @@ -5,6 +5,8 @@ #ifndef NET_SSL_SSL_CONFIG_SERVICE_DEFAULTS_H_ #define NET_SSL_SSL_CONFIG_SERVICE_DEFAULTS_H_ +#include + #include "net/base/net_export.h" #include "net/ssl/ssl_config_service.h" @@ -26,7 +28,7 @@ class NET_EXPORT SSLConfigServiceDefaults : public SSLConfigService { SSLContextConfig GetSSLContextConfig() override; bool CanShareConnectionWithClientCerts( - const std::string& hostname) const override; + std::string_view hostname) const override; private: // Default value of prefs. diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_android.cc b/naiveproxy/src/net/ssl/ssl_platform_key_android.cc index 0fd42ac502..cb7347d162 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_android.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_android.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -17,7 +18,6 @@ #include "net/base/net_errors.h" #include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/threaded_ssl_private_key.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/ecdsa.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/mem.h" @@ -73,7 +73,7 @@ class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { provider_name_(android::GetPrivateKeyClassName(key)) { key_.Reset(key); - absl::optional supports_rsa_no_padding; + std::optional supports_rsa_no_padding; for (uint16_t algorithm : SSLPrivateKey::DefaultAlgorithmPreferences( EVP_PKEY_id(pubkey_.get()), true /* include PSS */)) { const char* java_algorithm = GetJavaAlgorithm(algorithm); @@ -136,7 +136,7 @@ class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; } - absl::optional> padded = + std::optional> padded = AddPSSPadding(pubkey_.get(), md, base::make_span(digest, digest_len)); if (!padded) { return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc b/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc index d35a1b0c15..3bf95efdb0 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_mac.cc @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -29,7 +30,6 @@ #include "net/ssl/ssl_platform_key_util.h" #include "net/ssl/ssl_private_key.h" #include "net/ssl/threaded_ssl_private_key.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/mem.h" #include "third_party/boringssl/src/include/openssl/nid.h" @@ -123,7 +123,7 @@ class SSLPlatformKeySecKey : public ThreadedSSLPrivateKey::Delegate { } base::span digest = base::make_span(digest_buf, digest_len); - absl::optional> pss_storage; + std::optional> pss_storage; if (pss_fallback) { // Implement RSA-PSS by adding the padding manually and then using // kSecKeyAlgorithmRSASignatureRaw. diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_util.cc b/naiveproxy/src/net/ssl/ssl_platform_key_util.cc index 7c86967cab..1081224c44 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_util.cc +++ b/naiveproxy/src/net/ssl/ssl_platform_key_util.cc @@ -88,19 +88,19 @@ bool GetClientCertInfo(const X509Certificate* certificate, return true; } -absl::optional> AddPSSPadding( +std::optional> AddPSSPadding( EVP_PKEY* pubkey, const EVP_MD* md, base::span digest) { RSA* rsa = EVP_PKEY_get0_RSA(pubkey); if (!rsa) { - return absl::nullopt; + return std::nullopt; } std::vector ret(RSA_size(rsa)); if (digest.size() != EVP_MD_size(md) || !RSA_padding_add_PKCS1_PSS_mgf1(rsa, ret.data(), digest.data(), md, md, -1 /* salt length is digest length */)) { - return absl::nullopt; + return std::nullopt; } return ret; } diff --git a/naiveproxy/src/net/ssl/ssl_platform_key_util.h b/naiveproxy/src/net/ssl/ssl_platform_key_util.h index 5e26c93114..2c19588228 100644 --- a/naiveproxy/src/net/ssl/ssl_platform_key_util.h +++ b/naiveproxy/src/net/ssl/ssl_platform_key_util.h @@ -8,13 +8,13 @@ #include #include +#include #include #include "base/containers/span.h" #include "base/memory/scoped_refptr.h" #include "base/task/single_thread_task_runner.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/base.h" namespace net { @@ -42,7 +42,7 @@ NET_EXPORT_PRIVATE bool GetClientCertInfo(const X509Certificate* certificate, // Returns the encoded form of |digest| for use with RSA-PSS with |pubkey|, // using |md| as the hash function and MGF-1 function, and the digest size of // |md| as the salt length. -absl::optional> AddPSSPadding( +std::optional> AddPSSPadding( EVP_PKEY* pubkey, const EVP_MD* md, base::span digest); diff --git a/naiveproxy/src/net/ssl/ssl_server_config.h b/naiveproxy/src/net/ssl/ssl_server_config.h index a7ae034e71..b96fc619a6 100644 --- a/naiveproxy/src/net/ssl/ssl_server_config.h +++ b/naiveproxy/src/net/ssl/ssl_server_config.h @@ -7,6 +7,7 @@ #include +#include #include #include @@ -16,7 +17,6 @@ #include "net/base/net_export.h" #include "net/socket/next_proto.h" #include "net/ssl/ssl_config.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/base.h" namespace net { @@ -63,12 +63,12 @@ struct NET_EXPORT SSLServerConfig { // cipher_suite_for_testing, if set, causes the server to only support the // specified cipher suite in TLS 1.2 and below. This should only be used in // unit tests. - absl::optional cipher_suite_for_testing; + std::optional cipher_suite_for_testing; // signature_algorithm_for_testing, if set, causes the server to only support // the specified signature algorithm in TLS 1.2 and below. This should only be // used in unit tests. - absl::optional signature_algorithm_for_testing; + std::optional signature_algorithm_for_testing; // curves_for_testing, if not empty, specifies the list of NID values (e.g. // NID_X25519) to configure as supported curves for the TLS connection. @@ -114,7 +114,7 @@ struct NET_EXPORT SSLServerConfig { // If specified, causes the specified alert to be sent immediately after the // handshake. - absl::optional alert_after_handshake_for_testing; + std::optional alert_after_handshake_for_testing; // This is a workaround for BoringSSL's scopers not being copyable. See // https://crbug.com/boringssl/431. diff --git a/naiveproxy/src/net/ssl/test_ssl_config_service.cc b/naiveproxy/src/net/ssl/test_ssl_config_service.cc index dec8f97864..67e616f993 100644 --- a/naiveproxy/src/net/ssl/test_ssl_config_service.cc +++ b/naiveproxy/src/net/ssl/test_ssl_config_service.cc @@ -16,7 +16,7 @@ SSLContextConfig TestSSLConfigService::GetSSLContextConfig() { } bool TestSSLConfigService::CanShareConnectionWithClientCerts( - const std::string& hostname) const { + std::string_view hostname) const { return false; } diff --git a/naiveproxy/src/net/ssl/test_ssl_config_service.h b/naiveproxy/src/net/ssl/test_ssl_config_service.h index 822895a972..5b2df6f9ed 100644 --- a/naiveproxy/src/net/ssl/test_ssl_config_service.h +++ b/naiveproxy/src/net/ssl/test_ssl_config_service.h @@ -18,7 +18,7 @@ class TestSSLConfigService : public SSLConfigService { SSLContextConfig GetSSLContextConfig() override; bool CanShareConnectionWithClientCerts( - const std::string& hostname) const override; + std::string_view hostname) const override; private: SSLContextConfig config_; diff --git a/naiveproxy/src/net/test/cert_builder.cc b/naiveproxy/src/net/test/cert_builder.cc index 3d1b1ec253..5243f05ff6 100644 --- a/naiveproxy/src/net/test/cert_builder.cc +++ b/naiveproxy/src/net/test/cert_builder.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include "net/test/key_util.h" #include "net/test/test_data_directory.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/mem.h" #include "third_party/boringssl/src/pki/certificate_policies.h" @@ -260,13 +260,13 @@ std::array, 2> CertBuilder::CreateSimpleChain2() { } // static -absl::optional +std::optional CertBuilder::DefaultSignatureAlgorithmForKey(EVP_PKEY* key) { if (EVP_PKEY_id(key) == EVP_PKEY_RSA) return bssl::SignatureAlgorithm::kRsaPkcs1Sha256; if (EVP_PKEY_id(key) == EVP_PKEY_EC) return bssl::SignatureAlgorithm::kEcdsaSha256; - return absl::nullopt; + return std::nullopt; } // static @@ -364,11 +364,9 @@ std::string CertBuilder::SignatureAlgorithmToDer( // static std::string CertBuilder::MakeRandomHexString(size_t num_bytes) { - std::vector rand_bytes; - rand_bytes.resize(num_bytes); - - base::RandBytes(rand_bytes.data(), rand_bytes.size()); - return base::HexEncode(rand_bytes.data(), rand_bytes.size()); + std::vector rand_bytes(num_bytes); + base::RandBytes(rand_bytes); + return base::HexEncode(rand_bytes); } // static @@ -594,7 +592,7 @@ void CertBuilder::SetCrlDistributionPointUrls(const std::vector& urls) { void CertBuilder::SetIssuerTLV(base::span issuer_tlv) { if (issuer_tlv.empty()) - issuer_tlv_ = absl::nullopt; + issuer_tlv_ = std::nullopt; else issuer_tlv_ = std::string(issuer_tlv.begin(), issuer_tlv.end()); Invalidate(); @@ -797,8 +795,8 @@ void CertBuilder::SetPolicyMappings( } void CertBuilder::SetPolicyConstraints( - absl::optional require_explicit_policy, - absl::optional inhibit_policy_mapping) { + std::optional require_explicit_policy, + std::optional inhibit_policy_mapping) { if (!require_explicit_policy.has_value() && !inhibit_policy_mapping.has_value()) { EraseExtension(bssl::der::Input(bssl::kPolicyConstraintsOid)); @@ -816,14 +814,14 @@ void CertBuilder::SetPolicyConstraints( ASSERT_TRUE(CBB_init(cbb.get(), 64)); ASSERT_TRUE(CBB_add_asn1(cbb.get(), &policy_constraints, CBS_ASN1_SEQUENCE)); if (require_explicit_policy.has_value()) { - ASSERT_TRUE(CBB_add_asn1_uint64_with_tag( - &policy_constraints, *require_explicit_policy, - bssl::der::ContextSpecificPrimitive(0))); + ASSERT_TRUE(CBB_add_asn1_uint64_with_tag(&policy_constraints, + *require_explicit_policy, + CBS_ASN1_CONTEXT_SPECIFIC | 0)); } if (inhibit_policy_mapping.has_value()) { - ASSERT_TRUE(CBB_add_asn1_uint64_with_tag( - &policy_constraints, *inhibit_policy_mapping, - bssl::der::ContextSpecificPrimitive(1))); + ASSERT_TRUE(CBB_add_asn1_uint64_with_tag(&policy_constraints, + *inhibit_policy_mapping, + CBS_ASN1_CONTEXT_SPECIFIC | 1)); } SetExtension(bssl::der::Input(bssl::kPolicyConstraintsOid), @@ -1176,8 +1174,7 @@ void CertBuilder::InitFromCert(const bssl::der::Input& cert) { // version bool has_version; ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - bssl::der::kTagConstructed | bssl::der::kTagContextSpecific | 0, - &has_version)); + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0, &has_version)); if (has_version) { // TODO(mattm): could actually parse the version here instead of assuming // V3. @@ -1187,7 +1184,7 @@ void CertBuilder::InitFromCert(const bssl::der::Input& cert) { } // serialNumber - ASSERT_TRUE(tbs_certificate.SkipTag(bssl::der::kInteger)); + ASSERT_TRUE(tbs_certificate.SkipTag(CBS_ASN1_INTEGER)); // signature bssl::der::Input signature_algorithm_tlv; @@ -1198,7 +1195,7 @@ void CertBuilder::InitFromCert(const bssl::der::Input& cert) { signature_algorithm_ = *signature_algorithm; // issuer - ASSERT_TRUE(tbs_certificate.SkipTag(bssl::der::kSequence)); + ASSERT_TRUE(tbs_certificate.SkipTag(CBS_ASN1_SEQUENCE)); // validity bssl::der::Input validity_tlv; @@ -1206,7 +1203,7 @@ void CertBuilder::InitFromCert(const bssl::der::Input& cert) { validity_tlv_ = validity_tlv.AsString(); // subject - ASSERT_TRUE(tbs_certificate.SkipTag(bssl::der::kSequence)); + ASSERT_TRUE(tbs_certificate.SkipTag(CBS_ASN1_SEQUENCE)); // subjectPublicKeyInfo bssl::der::Input spki_tlv; @@ -1217,16 +1214,16 @@ void CertBuilder::InitFromCert(const bssl::der::Input& cert) { // issuerUniqueID bool unused; - ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - bssl::der::ContextSpecificPrimitive(1), &unused)); + ASSERT_TRUE( + tbs_certificate.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1, &unused)); // subjectUniqueID - ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - bssl::der::ContextSpecificPrimitive(2), &unused)); + ASSERT_TRUE( + tbs_certificate.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2, &unused)); // extensions - absl::optional extensions_tlv; + std::optional extensions_tlv; ASSERT_TRUE(tbs_certificate.ReadOptionalTag( - bssl::der::ContextSpecificConstructed(3), &extensions_tlv)); + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3, &extensions_tlv)); if (extensions_tlv) { std::map parsed_extensions; ASSERT_TRUE(ParseExtensions(extensions_tlv.value(), &parsed_extensions)); @@ -1364,7 +1361,7 @@ void CertBuilder::BuildSctListExtension(const std::string& pre_tbs_certificate, void CertBuilder::GenerateCertificate() { ASSERT_FALSE(cert_); - absl::optional signature_algorithm = + std::optional signature_algorithm = signature_algorithm_; if (!signature_algorithm) signature_algorithm = DefaultSignatureAlgorithmForKey(issuer_->GetKey()); diff --git a/naiveproxy/src/net/test/cert_builder.h b/naiveproxy/src/net/test/cert_builder.h index 594f185822..1aad6e6036 100644 --- a/naiveproxy/src/net/test/cert_builder.h +++ b/naiveproxy/src/net/test/cert_builder.h @@ -114,7 +114,7 @@ class CertBuilder { static std::array, 2> CreateSimpleChain2(); // Returns a compatible signature algorithm for |key|. - static absl::optional + static std::optional DefaultSignatureAlgorithmForKey(EVP_PKEY* key); // Signs |tbs_data| with |key| using |signature_algorithm| appending the @@ -231,8 +231,8 @@ class CertBuilder { // Sets the PolicyConstraints extension. If both |require_explicit_policy| // and |inhibit_policy_mapping| are nullopt, the PolicyConstraints extension // will removed. - void SetPolicyConstraints(absl::optional require_explicit_policy, - absl::optional inhibit_policy_mapping); + void SetPolicyConstraints(std::optional require_explicit_policy, + std::optional inhibit_policy_mapping); // Sets the inhibitAnyPolicy extension. void SetInhibitAnyPolicy(uint64_t skip_certs); @@ -418,9 +418,9 @@ class CertBuilder { bssl::CertificateVersion version_ = bssl::CertificateVersion::V3; std::string validity_tlv_; - absl::optional issuer_tlv_; + std::optional issuer_tlv_; std::string subject_tlv_; - absl::optional signature_algorithm_; + std::optional signature_algorithm_; std::string outer_signature_algorithm_tlv_; std::string tbs_signature_algorithm_tlv_; uint64_t serial_number_ = 0; diff --git a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc index 3167953b79..0f50e1fb32 100644 --- a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc +++ b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.cc @@ -7,6 +7,7 @@ #include #include +#include #include #include "base/files/file_path.h" @@ -52,7 +53,6 @@ #include "net/test/revocation_builder.h" #include "net/test/test_data_directory.h" #include "net/third_party/quiche/src/quiche/spdy/core/spdy_frame_builder.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/extended_key_usage.h" #include "url/origin.h" @@ -718,7 +718,7 @@ GURL EmbeddedTestServer::GetURL(base::StringPiece hostname, } url::Origin EmbeddedTestServer::GetOrigin( - const absl::optional& hostname) const { + const std::optional& hostname) const { if (hostname) return url::Origin::Create(GetURL(*hostname, "/")); return url::Origin::Create(base_url_); diff --git a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h index da5d1aefd3..f73f17c730 100644 --- a/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h +++ b/naiveproxy/src/net/test/embedded_test_server/embedded_test_server.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -31,7 +32,6 @@ #include "net/ssl/ssl_server_config.h" #include "net/test/cert_builder.h" #include "net/test/embedded_test_server/http_connection.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/pki/ocsp_revocation_status.h" #include "third_party/boringssl/src/pki/parse_certificate.h" #include "url/gurl.h" @@ -426,7 +426,7 @@ class EmbeddedTestServer { // Will use the GetURL() variant that takes a hostname as the base URL, if // `hostname` is non-null. url::Origin GetOrigin( - const absl::optional& hostname = absl::nullopt) const; + const std::optional& hostname = std::nullopt) const; // Returns the address list needed to connect to the server. [[nodiscard]] bool GetAddressList(AddressList* address_list) const; diff --git a/naiveproxy/src/net/test/embedded_test_server/http_request.h b/naiveproxy/src/net/test/embedded_test_server/http_request.h index de142120d5..c35fb580a9 100644 --- a/naiveproxy/src/net/test/embedded_test_server/http_request.h +++ b/naiveproxy/src/net/test/embedded_test_server/http_request.h @@ -9,12 +9,12 @@ #include #include +#include #include #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "net/ssl/ssl_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -73,7 +73,7 @@ struct HttpRequest { HeaderMap headers; std::string content; bool has_content = false; - absl::optional ssl_info; + std::optional ssl_info; }; // Parses the input data and produces a valid HttpRequest object. If there is diff --git a/naiveproxy/src/net/test/embedded_test_server/http_response.h b/naiveproxy/src/net/test/embedded_test_server/http_response.h index faa1af23b7..3ebfa88d6f 100644 --- a/naiveproxy/src/net/test/embedded_test_server/http_response.h +++ b/naiveproxy/src/net/test/embedded_test_server/http_response.h @@ -5,6 +5,7 @@ #ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ #define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_ +#include #include #include "base/compiler_specific.h" @@ -17,7 +18,6 @@ #include "base/strings/string_split.h" #include "base/time/time.h" #include "net/http/http_status_code.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net::test_server { @@ -96,7 +96,7 @@ class BasicHttpResponse : public HttpResponse { std::string reason() const { return reason_.value_or(GetHttpReasonPhrase(code_)); } - void set_reason(absl::optional reason) { + void set_reason(std::optional reason) { reason_ = std::move(reason); } @@ -126,7 +126,7 @@ class BasicHttpResponse : public HttpResponse { private: HttpStatusCode code_ = HTTP_OK; - absl::optional reason_; + std::optional reason_; std::string content_; std::string content_type_; base::StringPairs custom_headers_; diff --git a/naiveproxy/src/net/test/revocation_builder.cc b/naiveproxy/src/net/test/revocation_builder.cc index edad94c2dc..7426b1bd6b 100644 --- a/naiveproxy/src/net/test/revocation_builder.cc +++ b/naiveproxy/src/net/test/revocation_builder.cc @@ -4,6 +4,7 @@ #include "net/test/revocation_builder.h" +#include "base/containers/span.h" #include "base/functional/callback.h" #include "base/hash/sha1.h" #include "base/strings/string_piece.h" @@ -36,11 +37,10 @@ bool CBBAddBytes(CBB* cbb, base::StringPiece bytes) { bytes.size()); } -// Adds bytes (from fixed size array) to the given CBB. +// Adds bytes (specified as a span) to the given CBB. // The argument ordering follows the boringssl CBB_* api style. -template -bool CBBAddBytes(CBB* cbb, const uint8_t (&data)[N]) { - return CBB_add_bytes(cbb, data, N); +bool CBBAddBytes(CBB* cbb, base::span data) { + return CBB_add_bytes(cbb, data.data(), data.size()); } // Adds a GeneralizedTime value to the given CBB. @@ -133,7 +133,7 @@ std::string EncodeOCSPResponse( ocsp_response_bytes_sequence, ocsp_response_type, ocsp_response_octet_string; - if (!CBB_init(cbb.get(), 64 + response_type.Length() + response.size()) || + if (!CBB_init(cbb.get(), 64 + response_type.size() + response.size()) || !CBB_add_asn1(cbb.get(), &ocsp_response, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&ocsp_response, &ocsp_response_status, CBS_ASN1_ENUMERATED) || @@ -143,14 +143,14 @@ std::string EncodeOCSPResponse( return std::string(); } - if (response_type.Length()) { + if (!response_type.empty()) { if (!CBB_add_asn1(&ocsp_response, &ocsp_response_bytes, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || !CBB_add_asn1(&ocsp_response_bytes, &ocsp_response_bytes_sequence, CBS_ASN1_SEQUENCE) || !CBB_add_asn1(&ocsp_response_bytes_sequence, &ocsp_response_type, CBS_ASN1_OBJECT) || - !CBBAddBytes(&ocsp_response_type, response_type.AsStringView()) || + !CBBAddBytes(&ocsp_response_type, response_type) || !CBB_add_asn1(&ocsp_response_bytes_sequence, &ocsp_response_octet_string, CBS_ASN1_OCTETSTRING) || !CBBAddBytes(&ocsp_response_octet_string, response)) { @@ -326,7 +326,7 @@ std::string BuildOCSPResponse( std::string BuildOCSPResponseWithResponseData( EVP_PKEY* responder_key, const std::string& tbs_response_data, - absl::optional signature_algorithm) { + std::optional signature_algorithm) { // For a basic OCSP responder, responseType will be id-pkix-ocsp-basic. // // id-pkix-ocsp OBJECT IDENTIFIER ::= { id-ad-ocsp } @@ -468,7 +468,7 @@ std::string BuildCrl( const std::string& crl_issuer_subject, EVP_PKEY* crl_issuer_key, const std::vector& revoked_serials, - absl::optional signature_algorithm) { + std::optional signature_algorithm) { if (!signature_algorithm) { signature_algorithm = CertBuilder::DefaultSignatureAlgorithmForKey(crl_issuer_key); diff --git a/naiveproxy/src/net/test/revocation_builder.h b/naiveproxy/src/net/test/revocation_builder.h index 28bfc15f19..f4a6a8b13f 100644 --- a/naiveproxy/src/net/test/revocation_builder.h +++ b/naiveproxy/src/net/test/revocation_builder.h @@ -5,11 +5,11 @@ #ifndef NET_TEST_REVOCATION_BUILDER_H_ #define NET_TEST_REVOCATION_BUILDER_H_ +#include #include #include #include "base/time/time.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/pki/ocsp.h" #include "third_party/boringssl/src/pki/ocsp_revocation_status.h" @@ -54,18 +54,17 @@ std::string BuildOCSPResponse( std::string BuildOCSPResponseWithResponseData( EVP_PKEY* responder_key, const std::string& response_data, - absl::optional signature_algorithm = - absl::nullopt); + std::optional signature_algorithm = std::nullopt); // Creates a CRL issued by |crl_issuer_subject| and signed by |crl_issuer_key|, // marking |revoked_serials| as revoked. If |signature_algorithm| is nullopt, a // default algorithm will be chosen based on the key type. // Returns the DER-encoded CRL. -std::string BuildCrl(const std::string& crl_issuer_subject, - EVP_PKEY* crl_issuer_key, - const std::vector& revoked_serials, - absl::optional - signature_algorithm = absl::nullopt); +std::string BuildCrl( + const std::string& crl_issuer_subject, + EVP_PKEY* crl_issuer_key, + const std::vector& revoked_serials, + std::optional signature_algorithm = std::nullopt); std::string BuildCrlWithAlgorithmTlvAndDigest( const std::string& crl_issuer_subject, diff --git a/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc index 3c09372049..878f161bb1 100644 --- a/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc +++ b/naiveproxy/src/net/test/spawned_test_server/base_test_server.cc @@ -284,7 +284,7 @@ bool BaseTestServer::SetAndParseServerData(const std::string& server_data, return false; } - absl::optional port_value = parsed_json->GetDict().FindInt("port"); + std::optional port_value = parsed_json->GetDict().FindInt("port"); if (!port_value) { LOG(ERROR) << "Could not find port value"; return false; @@ -320,7 +320,7 @@ void BaseTestServer::CleanUpWhenStoppingServer() { started_ = false; } -absl::optional BaseTestServer::GenerateArguments() const { +std::optional BaseTestServer::GenerateArguments() const { base::Value::Dict arguments; arguments.Set("host", host_port_pair_.host()); arguments.Set("port", host_port_pair_.port()); @@ -349,7 +349,7 @@ absl::optional BaseTestServer::GenerateArguments() const { !base::PathExists(certificate_path)) { LOG(ERROR) << "Certificate path " << certificate_path.value() << " doesn't exist. Can't launch https server."; - return absl::nullopt; + return std::nullopt; } arguments.Set("cert-and-key-file", certificate_path.AsUTF8Unsafe()); } @@ -366,7 +366,7 @@ absl::optional BaseTestServer::GenerateArguments() const { if (it->IsAbsolute() && !base::PathExists(*it)) { LOG(ERROR) << "Client authority path " << it->value() << " doesn't exist. Can't launch https server."; - return absl::nullopt; + return std::nullopt; } ssl_client_certs.Append(it->AsUTF8Unsafe()); } @@ -376,7 +376,7 @@ absl::optional BaseTestServer::GenerateArguments() const { } } - return absl::make_optional(std::move(arguments)); + return std::make_optional(std::move(arguments)); } } // namespace net diff --git a/naiveproxy/src/net/test/spawned_test_server/base_test_server.h b/naiveproxy/src/net/test/spawned_test_server/base_test_server.h index 195c68dcdd..589f3f7d45 100644 --- a/naiveproxy/src/net/test/spawned_test_server/base_test_server.h +++ b/naiveproxy/src/net/test/spawned_test_server/base_test_server.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include @@ -20,7 +21,6 @@ #include "base/values.h" #include "net/base/host_port_pair.h" #include "net/cert/test_root_certs.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -223,7 +223,7 @@ class BaseTestServer { // { argument-name: argument-value, ... } // // Returns nullopt if an invalid configuration is specified. - absl::optional GenerateArguments() const; + std::optional GenerateArguments() const; private: void Init(const std::string& host); diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc index affc9c5932..491d8a7882 100644 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc +++ b/naiveproxy/src/net/test/spawned_test_server/local_test_server.cc @@ -100,7 +100,7 @@ bool LocalTestServer::StartInBackground() { return false; } - absl::optional> python_path = GetPythonPath(); + std::optional> python_path = GetPythonPath(); if (!python_path) { LOG(ERROR) << "Could not get Python path."; return false; @@ -166,12 +166,12 @@ bool LocalTestServer::Init(const base::FilePath& document_root) { return true; } -absl::optional> LocalTestServer::GetPythonPath() +std::optional> LocalTestServer::GetPythonPath() const { base::FilePath third_party_dir; if (!base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &third_party_dir)) { LOG(ERROR) << "Failed to get DIR_SRC_TEST_DATA_ROOT"; - return absl::nullopt; + return std::nullopt; } third_party_dir = third_party_dir.AppendASCII("third_party"); @@ -184,7 +184,7 @@ absl::optional> LocalTestServer::GetPythonPath() bool LocalTestServer::AddCommandLineArguments( base::CommandLine* command_line) const { - absl::optional arguments_dict = GenerateArguments(); + std::optional arguments_dict = GenerateArguments(); if (!arguments_dict) return false; diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server.h b/naiveproxy/src/net/test/spawned_test_server/local_test_server.h index 0ca80b0a11..4a39362874 100644 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server.h +++ b/naiveproxy/src/net/test/spawned_test_server/local_test_server.h @@ -5,6 +5,7 @@ #ifndef NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_ #define NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_ +#include #include #include "base/files/file_util.h" @@ -12,7 +13,6 @@ #include "base/process/process.h" #include "build/build_config.h" #include "net/test/spawned_test_server/base_test_server.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #if BUILDFLAG(IS_WIN) #include "base/win/scoped_handle.h" @@ -51,7 +51,7 @@ class LocalTestServer : public BaseTestServer { bool Stop(); // Returns the directories to use as the PYTHONPATH, or nullopt on error. - virtual absl::optional> GetPythonPath() const; + virtual std::optional> GetPythonPath() const; // Returns true if the base::FilePath for the testserver python script is // successfully stored in |*testserver_path|. diff --git a/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc b/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc index 9070b348e9..06d0c968d3 100644 --- a/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc +++ b/naiveproxy/src/net/test/spawned_test_server/local_test_server_posix.cc @@ -138,7 +138,7 @@ bool LocalTestServer::LaunchPython( return false; } - options.fds_to_remap.push_back(std::make_pair(pipefd[1], pipefd[1])); + options.fds_to_remap.emplace_back(pipefd[1], pipefd[1]); LOG(ERROR) << "Running: " << python_command.GetCommandLineString(); process_ = base::LaunchProcess(python_command, options); if (!process_.IsValid()) { diff --git a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc b/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc index 38c757303e..9eccc12b75 100644 --- a/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc +++ b/naiveproxy/src/net/test/spawned_test_server/remote_test_server.cc @@ -81,7 +81,7 @@ std::string GetSpawnerUrlBase() { if (!ReadFileToString(config_path, &config_json)) LOG(FATAL) << "Failed to read " << config_path.value(); - absl::optional config = base::JSONReader::Read(config_json); + std::optional config = base::JSONReader::Read(config_json); if (!config) LOG(FATAL) << "Failed to parse " << config_path.value(); @@ -119,7 +119,7 @@ bool RemoteTestServer::StartInBackground() { DCHECK(!started()); DCHECK(!start_request_); - absl::optional arguments_dict = GenerateArguments(); + std::optional arguments_dict = GenerateArguments(); if (!arguments_dict) return false; diff --git a/naiveproxy/src/net/test/test_doh_server.cc b/naiveproxy/src/net/test/test_doh_server.cc index e8f21cd986..c9f215c823 100644 --- a/naiveproxy/src/net/test/test_doh_server.cc +++ b/naiveproxy/src/net/test/test_doh_server.cc @@ -89,8 +89,7 @@ void TestDohServer::AddAddressRecord(std::string_view name, void TestDohServer::AddRecord(const DnsResourceRecord& record) { base::AutoLock lock(lock_); - records_.insert( - std::make_pair(std::make_pair(record.name, record.type), record)); + records_.emplace(std::pair(record.name, record.type), record); } bool TestDohServer::Start() { @@ -191,7 +190,7 @@ std::unique_ptr TestDohServer::HandleRequest( return MakeHttpErrorResponse(HTTP_BAD_REQUEST, "invalid DNS query"); } - absl::optional name = dns_names_util::NetworkToDottedName( + std::optional name = dns_names_util::NetworkToDottedName( dns_query.qname(), /*require_complete=*/true); if (!name) { DnsResponse response(dns_query.id(), /*is_authoritative=*/false, @@ -202,7 +201,7 @@ std::unique_ptr TestDohServer::HandleRequest( } query_qnames_.push_back(*name); - auto range = records_.equal_range(std::make_pair(*name, dns_query.qtype())); + auto range = records_.equal_range(std::pair(*name, dns_query.qtype())); std::vector answers; for (auto i = range.first; i != range.second; ++i) { answers.push_back(i->second); diff --git a/naiveproxy/src/net/test/test_doh_server.h b/naiveproxy/src/net/test/test_doh_server.h index e6a49c3054..4f4cf1bf32 100644 --- a/naiveproxy/src/net/test/test_doh_server.h +++ b/naiveproxy/src/net/test/test_doh_server.h @@ -90,7 +90,7 @@ class TestDohServer { std::unique_ptr HandleRequest( const test_server::HttpRequest& request); - absl::optional hostname_; + std::optional hostname_; base::Lock lock_; // The following fields are accessed from a background thread and protected by // `lock_`. diff --git a/naiveproxy/src/net/test/url_request/url_request_mock_data_job.h b/naiveproxy/src/net/test/url_request/url_request_mock_data_job.h index d0d1620a4a..bed67ae2cd 100644 --- a/naiveproxy/src/net/test/url_request/url_request_mock_data_job.h +++ b/naiveproxy/src/net/test/url_request/url_request_mock_data_job.h @@ -7,11 +7,11 @@ #include +#include #include #include "base/memory/weak_ptr.h" #include "net/url_request/url_request_job.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -66,7 +66,7 @@ class URLRequestMockDataJob : public URLRequestJob { void StartAsync(); - absl::optional headers_; + std::optional headers_; std::string data_; size_t data_offset_ = 0; bool request_client_certificate_; diff --git a/naiveproxy/src/net/third_party/nss/ssl/cmpcert.cc b/naiveproxy/src/net/third_party/nss/ssl/cmpcert.cc index 5a0eb6656c..4dd82a5938 100644 --- a/naiveproxy/src/net/third_party/nss/ssl/cmpcert.cc +++ b/naiveproxy/src/net/third_party/nss/ssl/cmpcert.cc @@ -90,8 +90,8 @@ bool MatchClientCertificateIssuers( // Look the parent up in the database and keep searching. SECItem issuer_item; - issuer_item.len = issuer.Length(); - issuer_item.data = const_cast(issuer.UnsafeData()); + issuer_item.len = issuer.size(); + issuer_item.data = const_cast(issuer.data()); ScopedCERTCertificate nextcert( CERT_FindCertByName(CERT_GetDefaultCertDB(), &issuer_item)); if (!nextcert) diff --git a/naiveproxy/src/net/third_party/quiche/BUILD.gn b/naiveproxy/src/net/third_party/quiche/BUILD.gn index 11171b237e..c7f80cc80d 100644 --- a/naiveproxy/src/net/third_party/quiche/BUILD.gn +++ b/naiveproxy/src/net/third_party/quiche/BUILD.gn @@ -49,6 +49,11 @@ config("quiche_config") { } component("quiche") { + # TODO(crbug.com/325102878): Remove once usage of the deprecated version of + # absl::HexStringToBytes have been removed. + cflags = [ + "-Wno-deprecated-declarations", + ] sources = [ "overrides/quiche_platform_impl/quiche_bug_tracker_impl.h", "overrides/quiche_platform_impl/quiche_client_stats_impl.h", diff --git a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_command_line_flags_impl.h b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_command_line_flags_impl.h index 809c9d63b1..2548d44df9 100644 --- a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_command_line_flags_impl.h +++ b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_command_line_flags_impl.h @@ -5,6 +5,7 @@ #ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_ #define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_ +#include #include #include @@ -14,7 +15,6 @@ #include "base/no_destructor.h" #include "net/third_party/quiche/src/quiche/common/platform/api/quiche_export.h" #include "net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace quiche { @@ -135,7 +135,7 @@ struct QuicheParseCommandLineFlagsResult { ~QuicheParseCommandLineFlagsResult(); std::vector non_flag_args; - absl::optional exit_status; + std::optional exit_status; }; QuicheParseCommandLineFlagsResult QuicheParseCommandLineFlagsHelper( diff --git a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc index 5435d4f7c4..d2131bf15b 100644 --- a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.cc @@ -10,12 +10,12 @@ namespace quiche { -absl::optional QuicheUtcDateTimeToUnixSecondsImpl(int year, - int month, - int day, - int hour, - int minute, - int second) { +std::optional QuicheUtcDateTimeToUnixSecondsImpl(int year, + int month, + int day, + int hour, + int minute, + int second) { struct tm tmp_tm; tmp_tm.tm_year = year - 1900; tmp_tm.tm_mon = month - 1; @@ -31,13 +31,13 @@ absl::optional QuicheUtcDateTimeToUnixSecondsImpl(int year, } int64_t result; if (!OPENSSL_tm_to_posix(&tmp_tm, &result)) { - return absl::nullopt; + return std::nullopt; } // Our desired behaviour is to return the following second for a leap second // assuming it is a valid time. if (leap_second) { if (!OPENSSL_posix_to_tm(result + 1, &tmp_tm)) { - return absl::nullopt; + return std::nullopt; } result++; } diff --git a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.h b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.h index 0ab8c884a1..b90ff2b7a1 100644 --- a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.h +++ b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_time_utils_impl.h @@ -6,13 +6,13 @@ #define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_TIME_UTILS_IMPL_H_ #include +#include #include "quiche/common/platform/api/quiche_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace quiche { -QUICHE_EXPORT absl::optional QuicheUtcDateTimeToUnixSecondsImpl( +QUICHE_EXPORT std::optional QuicheUtcDateTimeToUnixSecondsImpl( int year, int month, int day, diff --git a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc index c18b1af901..09a476ed7f 100644 --- a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -14,7 +15,6 @@ #include "third_party/abseil-cpp/absl/container/flat_hash_set.h" #include "third_party/abseil-cpp/absl/strings/str_cat.h" #include "third_party/abseil-cpp/absl/strings/str_replace.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/url_canon.h" #include "url/url_util.h" @@ -41,7 +41,7 @@ bool ExpandURITemplateImpl( return result; } -absl::optional AsciiUrlDecodeImpl(std::string_view input) { +std::optional AsciiUrlDecodeImpl(std::string_view input) { url::RawCanonOutputW<1024> canon_output; url::DecodeURLEscapeSequences(input, url::DecodeURLMode::kUTF8, &canon_output); @@ -49,7 +49,7 @@ absl::optional AsciiUrlDecodeImpl(std::string_view input) { output.reserve(canon_output.length()); for (uint16_t c : canon_output.view()) { if (c > std::numeric_limits::max()) { - return absl::nullopt; + return std::nullopt; } output += static_cast(c); } diff --git a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.h b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.h index 3a625b2e0f..54cd92b423 100644 --- a/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.h +++ b/naiveproxy/src/net/third_party/quiche/overrides/quiche_platform_impl/quiche_url_utils_impl.h @@ -5,13 +5,13 @@ #ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_URL_UTILS_IMPL_H_ #define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_URL_UTILS_IMPL_H_ +#include #include #include #include "quiche/common/platform/api/quiche_export.h" #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" #include "third_party/abseil-cpp/absl/container/flat_hash_set.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace quiche { @@ -27,8 +27,8 @@ QUICHE_EXPORT bool ExpandURITemplateImpl( absl::flat_hash_set* vars_found = nullptr); // Decodes a URL-encoded string and converts it to ASCII. If the decoded input -// contains non-ASCII characters, decoding fails and absl::nullopt is returned. -QUICHE_EXPORT absl::optional AsciiUrlDecodeImpl( +// contains non-ASCII characters, decoding fails and std::nullopt is returned. +QUICHE_EXPORT std::optional AsciiUrlDecodeImpl( std::string_view input); } // namespace quiche diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl b/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl index 9431ce4959..e904ef4414 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.bzl @@ -209,6 +209,7 @@ quiche_core_hdrs = [ "quic/core/frames/quic_path_challenge_frame.h", "quic/core/frames/quic_path_response_frame.h", "quic/core/frames/quic_ping_frame.h", + "quic/core/frames/quic_reset_stream_at_frame.h", "quic/core/frames/quic_retire_connection_id_frame.h", "quic/core/frames/quic_rst_stream_frame.h", "quic/core/frames/quic_stop_sending_frame.h", @@ -315,7 +316,6 @@ quiche_core_hdrs = [ "quic/core/quic_path_validator.h", "quic/core/quic_ping_manager.h", "quic/core/quic_process_packet_interface.h", - "quic/core/quic_protocol_flags_list.h", "quic/core/quic_received_packet_manager.h", "quic/core/quic_sent_packet_manager.h", "quic/core/quic_server_id.h", @@ -549,6 +549,7 @@ quiche_core_srcs = [ "quic/core/frames/quic_path_challenge_frame.cc", "quic/core/frames/quic_path_response_frame.cc", "quic/core/frames/quic_ping_frame.cc", + "quic/core/frames/quic_reset_stream_at_frame.cc", "quic/core/frames/quic_retire_connection_id_frame.cc", "quic/core/frames/quic_rst_stream_frame.cc", "quic/core/frames/quic_stop_sending_frame.cc", @@ -1497,6 +1498,7 @@ moqt_srcs = [ "quic/moqt/moqt_parser_test.cc", "quic/moqt/moqt_session.cc", "quic/moqt/moqt_session_test.cc", + "quic/moqt/moqt_subscribe_windows.cc", "quic/moqt/moqt_subscribe_windows_test.cc", "quic/moqt/moqt_track_test.cc", "quic/moqt/tools/chat_client_bin.cc", diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni b/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni index 9e3a202f87..f27df5bc66 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.gni @@ -209,6 +209,7 @@ quiche_core_hdrs = [ "src/quiche/quic/core/frames/quic_path_challenge_frame.h", "src/quiche/quic/core/frames/quic_path_response_frame.h", "src/quiche/quic/core/frames/quic_ping_frame.h", + "src/quiche/quic/core/frames/quic_reset_stream_at_frame.h", "src/quiche/quic/core/frames/quic_retire_connection_id_frame.h", "src/quiche/quic/core/frames/quic_rst_stream_frame.h", "src/quiche/quic/core/frames/quic_stop_sending_frame.h", @@ -315,7 +316,6 @@ quiche_core_hdrs = [ "src/quiche/quic/core/quic_path_validator.h", "src/quiche/quic/core/quic_ping_manager.h", "src/quiche/quic/core/quic_process_packet_interface.h", - "src/quiche/quic/core/quic_protocol_flags_list.h", "src/quiche/quic/core/quic_received_packet_manager.h", "src/quiche/quic/core/quic_sent_packet_manager.h", "src/quiche/quic/core/quic_server_id.h", @@ -549,6 +549,7 @@ quiche_core_srcs = [ "src/quiche/quic/core/frames/quic_path_challenge_frame.cc", "src/quiche/quic/core/frames/quic_path_response_frame.cc", "src/quiche/quic/core/frames/quic_ping_frame.cc", + "src/quiche/quic/core/frames/quic_reset_stream_at_frame.cc", "src/quiche/quic/core/frames/quic_retire_connection_id_frame.cc", "src/quiche/quic/core/frames/quic_rst_stream_frame.cc", "src/quiche/quic/core/frames/quic_stop_sending_frame.cc", @@ -1501,6 +1502,7 @@ moqt_srcs = [ "src/quiche/quic/moqt/moqt_parser_test.cc", "src/quiche/quic/moqt/moqt_session.cc", "src/quiche/quic/moqt/moqt_session_test.cc", + "src/quiche/quic/moqt/moqt_subscribe_windows.cc", "src/quiche/quic/moqt/moqt_subscribe_windows_test.cc", "src/quiche/quic/moqt/moqt_track_test.cc", "src/quiche/quic/moqt/tools/chat_client_bin.cc", diff --git a/naiveproxy/src/net/third_party/quiche/src/build/source_list.json b/naiveproxy/src/net/third_party/quiche/src/build/source_list.json index 2971cf818a..0f63fbd1d3 100644 --- a/naiveproxy/src/net/third_party/quiche/src/build/source_list.json +++ b/naiveproxy/src/net/third_party/quiche/src/build/source_list.json @@ -208,6 +208,7 @@ "quiche/quic/core/frames/quic_path_challenge_frame.h", "quiche/quic/core/frames/quic_path_response_frame.h", "quiche/quic/core/frames/quic_ping_frame.h", + "quiche/quic/core/frames/quic_reset_stream_at_frame.h", "quiche/quic/core/frames/quic_retire_connection_id_frame.h", "quiche/quic/core/frames/quic_rst_stream_frame.h", "quiche/quic/core/frames/quic_stop_sending_frame.h", @@ -314,7 +315,6 @@ "quiche/quic/core/quic_path_validator.h", "quiche/quic/core/quic_ping_manager.h", "quiche/quic/core/quic_process_packet_interface.h", - "quiche/quic/core/quic_protocol_flags_list.h", "quiche/quic/core/quic_received_packet_manager.h", "quiche/quic/core/quic_sent_packet_manager.h", "quiche/quic/core/quic_server_id.h", @@ -548,6 +548,7 @@ "quiche/quic/core/frames/quic_path_challenge_frame.cc", "quiche/quic/core/frames/quic_path_response_frame.cc", "quiche/quic/core/frames/quic_ping_frame.cc", + "quiche/quic/core/frames/quic_reset_stream_at_frame.cc", "quiche/quic/core/frames/quic_retire_connection_id_frame.cc", "quiche/quic/core/frames/quic_rst_stream_frame.cc", "quiche/quic/core/frames/quic_stop_sending_frame.cc", @@ -1500,6 +1501,7 @@ "quiche/quic/moqt/moqt_parser_test.cc", "quiche/quic/moqt/moqt_session.cc", "quiche/quic/moqt/moqt_session_test.cc", + "quiche/quic/moqt/moqt_subscribe_windows.cc", "quiche/quic/moqt/moqt_subscribe_windows_test.cc", "quiche/quic/moqt/moqt_track_test.cc", "quiche/quic/moqt/tools/chat_client_bin.cc", diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel b/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel index a25331bc06..e150aa1acb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/BUILD.bazel @@ -50,10 +50,7 @@ cc_library( cc_library( name = "quic_flags_list", - textual_hdrs = [ - "quic/core/quic_flags_list.h", - "quic/core/quic_protocol_flags_list.h", - ], + textual_hdrs = ["quic/core/quic_flags_list.h"], ) cc_library( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h index 5fb23bf709..c85f32d099 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/api/quiche_flags.h @@ -21,7 +21,7 @@ // Flags accessed via GetQuicheFlag are permanent flags used to control QUICHE // library behavior. The current list is available in the -// quiche/quic/core/quic_protocol_flags_list.h file. +// quiche/common/quiche_protocol_flags_list.h file. #define GetQuicheFlag(flag) GetQuicheFlagImpl(flag) #define SetQuicheFlag(flag, value) SetQuicheFlagImpl(flag, value) diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc index eb609835fa..d753bd7638 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.cc @@ -8,30 +8,6 @@ #include "quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \ - type FLAGS_##flag = value; - -#define DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES(type, flag, internal_value, \ - external_value, doc) \ - type FLAGS_##flag = external_value; - -// Preprocessor macros can only have one definition. -// Select the right macro based on the number of arguments. -#define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6 -#define QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(...) \ - GET_6TH_ARG(__VA_ARGS__, DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES, \ - DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE) -#define QUIC_PROTOCOL_FLAG(...) \ - QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__) - -#include "quiche/quic/core/quic_protocol_flags_list.h" - -#undef QUIC_PROTOCOL_FLAG -#undef QUIC_PROTOCOL_FLAG_MACRO_CHOOSER -#undef GET_6TH_ARG -#undef DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES -#undef DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE - #define QUICHE_PROTOCOL_FLAG(type, flag, value, doc) type FLAGS_##flag = value; #include "quiche/common/quiche_protocol_flags_list.h" #undef QUICHE_PROTOCOL_FLAG diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h index 4565cd8d5d..474356f385 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_flags_impl.h @@ -17,12 +17,6 @@ #include "quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -// Protocol flags. TODO(bnc): Move to quiche_protocol_flags_list.h. -#define QUIC_PROTOCOL_FLAG(type, flag, ...) \ - QUICHE_EXPORT extern type FLAGS_##flag; -#include "quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG - // Protocol flags. #define QUICHE_PROTOCOL_FLAG(type, flag, ...) \ QUICHE_EXPORT extern type FLAGS_##flag; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc index 933b996af5..ccdbff3ff6 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.cc @@ -10,16 +10,16 @@ QuicheFlagSaverImpl::QuicheFlagSaverImpl() { #define QUIC_FLAG(flag, value) saved_##flag##_ = FLAGS_##flag; #include "quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; -#include "quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag; +#include "quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG } QuicheFlagSaverImpl::~QuicheFlagSaverImpl() { #define QUIC_FLAG(flag, value) FLAGS_##flag = saved_##flag##_; #include "quiche/quic/core/quic_flags_list.h" // NOLINT #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; -#include "quiche/quic/core/quic_protocol_flags_list.h" // NOLINT -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_; +#include "quiche/common/quiche_protocol_flags_list.h" // NOLINT +#undef QUICHE_PROTOCOL_FLAG } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h index 258b86286c..4dccfac1ad 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/platform/default/quiche_platform_impl/quiche_test_impl.h @@ -25,9 +25,9 @@ class QuicheFlagSaverImpl { #include "quiche/quic/core/quic_flags_list.h" #undef QUIC_FLAG -#define QUIC_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; -#include "quiche/quic/core/quic_protocol_flags_list.h" -#undef QUIC_PROTOCOL_FLAG +#define QUICHE_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_; +#include "quiche/common/quiche_protocol_flags_list.h" +#undef QUICHE_PROTOCOL_FLAG }; class ScopedEnvironmentForThreadsImpl {}; @@ -53,4 +53,6 @@ inline std::string QuicheGetTestMemoryCachePathImpl() { return "quiche/quic/test_tools/quic_http_response_cache_data"; } +class QuicheScopedDisableExitOnDFatalImpl {}; + #endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_TEST_IMPL_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h index 90d21a361c..9e84b688af 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_protocol_flags_list.h @@ -9,6 +9,236 @@ #if defined(QUICHE_PROTOCOL_FLAG) +QUICHE_PROTOCOL_FLAG( + bool, quic_allow_chlo_buffering, true, + "If true, allows packets to be buffered in anticipation of a " + "future CHLO, and allow CHLO packets to be buffered until next " + "iteration of the event loop.") + +QUICHE_PROTOCOL_FLAG(bool, quic_disable_pacing_for_perf_tests, false, + "If true, disable pacing in QUIC") + +// Note that single-packet CHLOs are only enforced for Google QUIC versions that +// do not use CRYPTO frames. This currently means only Q043 and Q046. All other +// versions of QUIC (both Google QUIC and IETF) allow multi-packet CHLOs +// regardless of the value of this flag. +QUICHE_PROTOCOL_FLAG(bool, quic_enforce_single_packet_chlo, true, + "If true, enforce that sent QUIC CHLOs fit in one packet. " + "Only applies to Q043 and Q046.") + +// Currently, this number is quite conservative. At a hypothetical 1000 qps, +// this means that the longest time-wait list we should see is: +// 200 seconds * 1000 qps = 200000. +// Of course, there are usually many queries per QUIC connection, so we allow a +// factor of 3 leeway. +QUICHE_PROTOCOL_FLAG(int64_t, quic_time_wait_list_max_connections, 600000, + "Maximum number of connections on the time-wait list. " + "A negative value implies no configured limit.") + +QUICHE_PROTOCOL_FLAG( + int64_t, quic_time_wait_list_seconds, 200, + "Time period for which a given connection_id should live in " + "the time-wait state.") + +// This number is relatively conservative. For example, there are at most 1K +// queued stateless resets, which consume 1K * 21B = 21KB. +QUICHE_PROTOCOL_FLAG( + uint64_t, quic_time_wait_list_max_pending_packets, 1024, + "Upper limit of pending packets in time wait list when writer is blocked.") + +// Stop sending a reset if the recorded number of addresses that server has +// recently sent stateless reset to exceeds this limit. +QUICHE_PROTOCOL_FLAG(uint64_t, quic_max_recent_stateless_reset_addresses, 1024, + "Max number of recorded recent reset addresses.") + +// After this timeout, recent reset addresses will be cleared. +// FLAGS_quic_max_recent_stateless_reset_addresses * (1000ms / +// FLAGS_quic_recent_stateless_reset_addresses_lifetime_ms) is roughly the max +// reset per second. For example, 1024 * (1000ms / 1000ms) = 1K reset per +// second. +QUICHE_PROTOCOL_FLAG( + uint64_t, quic_recent_stateless_reset_addresses_lifetime_ms, 1000, + "Max time that a client address lives in recent reset addresses set.") + +QUICHE_PROTOCOL_FLAG( + double, quic_bbr_cwnd_gain, 2.0f, + "Congestion window gain for QUIC BBR during PROBE_BW phase.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_buffered_data_threshold, 8 * 1024, + "If buffered data in QUIC stream is less than this " + "threshold, buffers all provided data or asks upper layer for more data") + +QUICHE_PROTOCOL_FLAG( + uint64_t, quic_send_buffer_max_data_slice_size, 4 * 1024, + "Max size of data slice in bytes for QUIC stream send buffer.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_lumpy_pacing_size, 2, + "Number of packets that the pacing sender allows in bursts during " + "pacing. This flag is ignored if a flow's estimated bandwidth is " + "lower than 1200 kbps.") + +QUICHE_PROTOCOL_FLAG( + double, quic_lumpy_pacing_cwnd_fraction, 0.25f, + "Congestion window fraction that the pacing sender allows in bursts " + "during pacing.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_lumpy_pacing_min_bandwidth_kbps, 1200, + "The minimum estimated client bandwidth below which the pacing sender will " + "not allow bursts.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_max_pace_time_into_future_ms, 10, + "Max time that QUIC can pace packets into the future in ms.") + +QUICHE_PROTOCOL_FLAG( + double, quic_pace_time_into_future_srtt_fraction, + 0.125f, // One-eighth smoothed RTT + "Smoothed RTT fraction that a connection can pace packets into the future.") + +QUICHE_PROTOCOL_FLAG( + bool, quic_export_write_path_stats_at_server, false, + "If true, export detailed write path statistics at server.") + +QUICHE_PROTOCOL_FLAG(bool, quic_disable_version_negotiation_grease_randomness, + false, + "If true, use predictable version negotiation versions.") + +QUICHE_PROTOCOL_FLAG(bool, quic_enable_http3_grease_randomness, true, + "If true, use random greased settings and frames.") + +QUICHE_PROTOCOL_FLAG(int64_t, quic_max_tracked_packet_count, 10000, + "Maximum number of tracked packets.") + +QUICHE_PROTOCOL_FLAG( + bool, quic_client_convert_http_header_name_to_lowercase, true, + "If true, HTTP request header names sent from QuicSpdyClientBase(and " + "descendants) will be automatically converted to lower case.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_probe_bw_base_duration_ms, 2000, + "The default minimum duration for BBRv2-native probes, in milliseconds.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_probe_bw_max_rand_duration_ms, 1000, + "The default upper bound of the random amount of BBRv2-native " + "probes, in milliseconds.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_probe_rtt_period_ms, 10000, + "The default period for entering PROBE_RTT, in milliseconds.") + +QUICHE_PROTOCOL_FLAG( + double, quic_bbr2_default_loss_threshold, 0.02, + "The default loss threshold for QUIC BBRv2, should be a value " + "between 0 and 1.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_startup_full_loss_count, 8, + "The default minimum number of loss marking events to exit STARTUP.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_probe_bw_full_loss_count, 2, + "The default minimum number of loss marking events to exit PROBE_UP phase.") + +QUICHE_PROTOCOL_FLAG( + double, quic_bbr2_default_inflight_hi_headroom, 0.15, + "The default fraction of unutilized headroom to try to leave in path " + "upon high loss.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_bbr2_default_initial_ack_height_filter_window, 10, + "The default initial value of the max ack height filter's window length.") + +QUICHE_PROTOCOL_FLAG( + double, quic_ack_aggregation_bandwidth_threshold, 1.0, + "If the bandwidth during ack aggregation is smaller than (estimated " + "bandwidth * this flag), consider the current aggregation completed " + "and starts a new one.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_anti_amplification_factor, 3, + "Anti-amplification factor. Before address validation, server will " + "send no more than factor times bytes received.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_max_buffered_crypto_bytes, + 16 * 1024, // 16 KB + "The maximum amount of CRYPTO frame data that can be buffered.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_max_aggressive_retransmittable_on_wire_ping_count, 5, + "Maximum number of consecutive pings that can be sent with the " + "aggressive initial retransmittable on the wire timeout if there is " + "no new stream data received. After this limit, the timeout will be " + "doubled each ping until it exceeds the default ping timeout.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_max_retransmittable_on_wire_ping_count, 1000, + "Maximum number of pings that can be sent with the retransmittable " + "on the wire timeout, over the lifetime of a connection. After this " + "limit, the timeout will be the default ping timeout.") + +QUICHE_PROTOCOL_FLAG(int32_t, quic_max_congestion_window, 2000, + "The maximum congestion window in packets.") + +QUICHE_PROTOCOL_FLAG( + int32_t, quic_max_streams_window_divisor, 2, + "The divisor that controls how often MAX_STREAMS frame is sent.") + +QUICHE_PROTOCOL_FLAG( + uint64_t, quic_key_update_confidentiality_limit, 0, + "If non-zero and key update is allowed, the maximum number of " + "packets sent for each key phase before initiating a key update.") + +QUICHE_PROTOCOL_FLAG(bool, quic_disable_client_tls_zero_rtt, false, + "If true, QUIC client with TLS will not try 0-RTT.") + +QUICHE_PROTOCOL_FLAG(bool, quic_disable_server_tls_resumption, false, + "If true, QUIC server will disable TLS resumption by not " + "issuing or processing session tickets.") + +QUICHE_PROTOCOL_FLAG(bool, quic_defer_send_in_response, true, + "If true, QUIC servers will defer sending in response to " + "incoming packets by default.") + +QUICHE_PROTOCOL_FLAG( + bool, quic_header_size_limit_includes_overhead, true, + "If true, QUIC QPACK decoder includes 32-bytes overheader per entry while " + "comparing request/response header size against its upper limit.") + +QUICHE_PROTOCOL_FLAG( + bool, quic_reject_retry_token_in_initial_packet, false, + "If true, always reject retry_token received in INITIAL packets") + +QUICHE_PROTOCOL_FLAG(bool, quic_use_lower_server_response_mtu_for_test, false, + "If true, cap server response packet size at 1250.") + +QUICHE_PROTOCOL_FLAG(bool, quic_enforce_strict_amplification_factor, false, + "If true, enforce strict amplification factor") + +QUICHE_PROTOCOL_FLAG(bool, quic_bounded_crypto_send_buffer, false, + "If true, close the connection if a crypto send buffer " + "exceeds its size limit.") + +QUICHE_PROTOCOL_FLAG(bool, quic_interval_set_enable_add_optimization, true, + "If true, enable an optimization in QuicIntervalSet") + +QUICHE_PROTOCOL_FLAG(bool, quic_server_disable_qpack_dynamic_table, false, + "If true, disables use of the QPACK dynamic table in " + "servers, both for decoding context (requests) and for " + "encoding context (responses).") + +QUICHE_PROTOCOL_FLAG( + bool, quic_enable_chaos_protection, true, + "If true, use chaos protection to randomize client initials.") + +QUICHE_PROTOCOL_FLAG(bool, quic_always_support_server_preferred_address, false, + "If false, the kSPAD connection option is required to use " + "QUIC server preferred address support.") + QUICHE_PROTOCOL_FLAG(bool, quiche_oghttp2_debug_trace, false, "If true, emits trace logs for HTTP/2 events.") diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h index ca1ef7bdc2..187e36217b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/common/quiche_stream.h @@ -131,13 +131,21 @@ class QUICHE_EXPORT StreamWriteOptions { public: StreamWriteOptions() = default; - // If send_fin() is sent to true, the write operation also sends a FIN on the + // If send_fin() is set to true, the write operation also sends a FIN on the // stream. bool send_fin() const { return send_fin_; } void set_send_fin(bool send_fin) { send_fin_ = send_fin; } + // If buffer_unconditionally() is set to true, the write operation will buffer + // data even if the internal buffer limit is exceeded. + bool buffer_unconditionally() const { return buffer_unconditionally_; } + void set_buffer_unconditionally(bool value) { + buffer_unconditionally_ = value; + } + private: bool send_fin_ = false; + bool buffer_unconditionally_ = false; }; inline constexpr StreamWriteOptions kDefaultStreamWriteOptions = diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc index b7dd1f8f5c..211d26452b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/http2/adapter/header_validator.cc @@ -17,47 +17,45 @@ namespace adapter { namespace { // From RFC 9110 Section 5.6.2. -const absl::string_view kHttpTokenChars = +constexpr absl::string_view kHttpTokenChars = "!#$%&'*+-.^_`|~0123456789" "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; -const absl::string_view kHttp2HeaderNameAllowedChars = +constexpr absl::string_view kHttp2HeaderNameAllowedChars = "!#$%&'*+-.0123456789" "^_`abcdefghijklmnopqrstuvwxyz|~"; -const absl::string_view kHttp2HeaderValueAllowedChars = +constexpr absl::string_view kHttp2HeaderValueAllowedChars = "\t " "!\"#$%&'()*+,-./" "0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`" "abcdefghijklmnopqrstuvwxyz{|}~"; -const absl::string_view kHttp2StatusValueAllowedChars = "0123456789"; +constexpr absl::string_view kHttp2StatusValueAllowedChars = "0123456789"; -const absl::string_view kValidAuthorityChars = +constexpr absl::string_view kValidAuthorityChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()[" "]*+,;=:"; -const absl::string_view kValidPathChars = +constexpr absl::string_view kValidPathChars = "/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()" "*+,;=:@?"; -const absl::string_view kValidPathCharsWithFragment = +constexpr absl::string_view kValidPathCharsWithFragment = "/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~%!$&'()" "*+,;=:@?#"; using CharMap = std::array; -CharMap BuildValidCharMap(absl::string_view valid_chars) { - CharMap map; - map.fill(false); +constexpr CharMap BuildValidCharMap(absl::string_view valid_chars) { + CharMap map = {}; for (char c : valid_chars) { - // Cast to uint8_t, guaranteed to have 8 bits. A char may have more, leading - // to possible indices above 256. + // An array index must be a nonnegative integer, hence the cast to uint8_t. map[static_cast(c)] = true; } return map; } -CharMap AllowObsText(CharMap map) { +constexpr CharMap AllowObsText(CharMap map) { // Characters above 0x80 are allowed in header field values as `obs-text` in // RFC 7230. for (uint8_t c = 0xff; c >= 0x80; --c) { @@ -76,13 +74,13 @@ bool AllCharsInMap(absl::string_view str, const CharMap& map) { } bool IsValidStatus(absl::string_view status) { - static const CharMap valid_chars = + static constexpr CharMap valid_chars = BuildValidCharMap(kHttp2StatusValueAllowedChars); return AllCharsInMap(status, valid_chars); } bool IsValidMethod(absl::string_view method) { - static const CharMap valid_chars = BuildValidCharMap(kHttpTokenChars); + static constexpr CharMap valid_chars = BuildValidCharMap(kHttpTokenChars); return AllCharsInMap(method, valid_chars); } @@ -244,16 +242,16 @@ bool HeaderValidator::FinishHeaderBlock(HeaderType type) { } bool HeaderValidator::IsValidHeaderName(absl::string_view name) { - static const CharMap valid_chars = + static constexpr CharMap valid_chars = BuildValidCharMap(kHttp2HeaderNameAllowedChars); return AllCharsInMap(name, valid_chars); } bool HeaderValidator::IsValidHeaderValue(absl::string_view value, ObsTextOption option) { - static const CharMap valid_chars = + static constexpr CharMap valid_chars = BuildValidCharMap(kHttp2HeaderValueAllowedChars); - static const CharMap valid_chars_with_obs_text = + static constexpr CharMap valid_chars_with_obs_text = AllowObsText(BuildValidCharMap(kHttp2HeaderValueAllowedChars)); return AllCharsInMap(value, option == ObsTextOption::kAllow ? valid_chars_with_obs_text @@ -261,13 +259,14 @@ bool HeaderValidator::IsValidHeaderValue(absl::string_view value, } bool HeaderValidator::IsValidAuthority(absl::string_view authority) { - static const CharMap valid_chars = BuildValidCharMap(kValidAuthorityChars); + static constexpr CharMap valid_chars = + BuildValidCharMap(kValidAuthorityChars); return AllCharsInMap(authority, valid_chars); } bool HeaderValidator::IsValidPath(absl::string_view path, bool allow_fragment) { - static const CharMap valid_chars = BuildValidCharMap(kValidPathChars); - static const CharMap valid_chars_with_fragment = + static constexpr CharMap valid_chars = BuildValidCharMap(kValidPathChars); + static constexpr CharMap valid_chars_with_fragment = BuildValidCharMap(kValidPathCharsWithFragment); if (allow_fragment) { return AllCharsInMap(path, valid_chars_with_fragment); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_batch_writer_test.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_batch_writer_test.h index 7fa200d7c6..71c59b322e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_batch_writer_test.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/batch_writer/quic_batch_writer_test.h @@ -231,6 +231,8 @@ class QUICHE_EXPORT QuicUdpBatchWriterIOTest QuicUdpSocketApi::ReadPacketResult result; result.packet_buffer = {&packet_buffer_[0], sizeof(packet_buffer_)}; result.control_buffer = {&control_buffer_[0], sizeof(control_buffer_)}; + ASSERT_TRUE(QuicUdpSocketApi().WaitUntilReadable( + peer_socket_, QuicTime::Delta::FromSeconds(1))); QuicUdpSocketApi().ReadPacket( peer_socket_, quic::QuicUdpPacketInfoBitMask({QuicUdpPacketInfoBit::V4_SELF_IP, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc index ae4d6e3c38..800efbd7a0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc @@ -12,6 +12,7 @@ #include "quiche/quic/core/crypto/quic_decrypter.h" #include "quiche/quic/core/crypto/quic_encrypter.h" #include "quiche/quic/core/frames/quic_ack_frequency_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_framer.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_utils.h" @@ -78,6 +79,7 @@ class ChloFramerVisitor : public QuicFramerVisitorInterface, bool OnMessageFrame(const QuicMessageFrame& frame) override; bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override; bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override; + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override; void OnPacketComplete() override {} bool IsValidStatelessResetToken( const StatelessResetToken& token) const override; @@ -207,6 +209,11 @@ bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/, return true; } +bool ChloFramerVisitor::OnResetStreamAtFrame( + const QuicResetStreamAtFrame& /*frame*/) { + return true; +} + bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/, QuicPacketNumber /*end*/) { return true; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h index 0a945dbce8..9162f62db5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/congestion_control/tcp_cubic_sender_bytes.h @@ -25,7 +25,7 @@ namespace quic { class RttStats; // Maximum window to allow when doing bandwidth resumption. -const QuicPacketCount kMaxResumptionCongestionWindow = 200; +inline constexpr QuicPacketCount kMaxResumptionCongestionWindow = 200; namespace test { class TcpCubicSenderBytesPeer; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h index b963034266..b2a9738499 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/proof_source.h @@ -5,17 +5,26 @@ #ifndef QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ #define QUICHE_QUIC_CORE_CRYPTO_PROOF_SOURCE_H_ +#include +#include #include +#include #include #include +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "absl/types/variant.h" +#include "openssl/base.h" +#include "openssl/pool.h" #include "openssl/ssl.h" #include "quiche/quic/core/crypto/certificate_view.h" #include "quiche/quic/core/crypto/quic_crypto_proof.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/quic_versions.h" -#include "quiche/quic/platform/api/quic_export.h" #include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_export.h" #include "quiche/common/platform/api/quiche_reference_counted.h" namespace quic { @@ -245,27 +254,44 @@ class QUICHE_EXPORT ProofSourceHandleCallback { public: virtual ~ProofSourceHandleCallback() = default; + // Configuration to use for configuring the SSL object when handshaking + // locally. + struct LocalSSLConfig { + const ProofSource::Chain* chain; + QuicDelayedSSLConfig delayed_ssl_config; + }; + + // Functor to call to configure the SSL object. This functor must not be + // called more than once. + using ConfigureSSLFunc = + std::function; + + // Configuration to use for configuring the SSL object when using a + // handshake-hints server. + struct HintsSSLConfig { + ConfigureSSLFunc configure_ssl; + QuicDelayedSSLConfig delayed_ssl_config; + }; + + using SSLConfig = absl::variant; + // Called when a ProofSourceHandle::SelectCertificate operation completes. // |ok| indicates whether the operation was successful. // |is_sync| indicates whether the operation completed synchronously, i.e. // whether it is completed before ProofSourceHandle::SelectCertificate // returned. - // |chain| the certificate chain in leaf-first order. - // |handshake_hints| (optional) handshake hints that can be used by - // SSL_set_handshake_hints. + // |ssl_config| configuration used to configure the SSL object. // |ticket_encryption_key| (optional) encryption key to be used for minting // TLS resumption tickets. // |cert_matched_sni| is true if the certificate matched the SNI hostname, // false if a non-matching default cert was used. - // |delayed_ssl_config| contains SSL configs to be applied on the SSL object. // // When called asynchronously(is_sync=false), this method will be responsible // to continue the handshake from where it left off. - virtual void OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, - absl::string_view ticket_encryption_key, bool cert_matched_sni, - QuicDelayedSSLConfig delayed_ssl_config) = 0; + virtual void OnSelectCertificateDone(bool ok, bool is_sync, + SSLConfig ssl_config, + absl::string_view ticket_encryption_key, + bool cert_matched_sni) = 0; // Called when a ProofSourceHandle::ComputeSignature operation completes. virtual void OnComputeSignatureDone( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc index 51311bcfd4..9bf6dcaaa7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.cc @@ -4,12 +4,20 @@ #include "quiche/quic/core/crypto/tls_server_connection.h" +#include +#include +#include +#include + +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "openssl/base.h" #include "openssl/ssl.h" #include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/tls_connection.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_flag_utils.h" -#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/common/platform/api/quiche_logging.h" namespace quic { @@ -59,6 +67,12 @@ bssl::UniquePtr TlsServerConnection::CreateSslCtx( return ssl_ctx; } +absl::Status TlsServerConnection::ConfigureSSL( + ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl) { + return std::move(configure_ssl)(*ssl(), // never nullptr + TlsServerConnection::kPrivateKeyMethod); +} + void TlsServerConnection::SetCertChain( const std::vector& cert_chain) { SSL_set_chain_and_key(ssl(), cert_chain.data(), cert_chain.size(), nullptr, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.h index bdb58be476..9301f2cb19 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/crypto/tls_server_connection.h @@ -5,9 +5,18 @@ #ifndef QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ #define QUICHE_QUIC_CORE_CRYPTO_TLS_SERVER_CONNECTION_H_ +#include +#include +#include + +#include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "openssl/base.h" +#include "openssl/ssl.h" #include "quiche/quic/core/crypto/proof_source.h" #include "quiche/quic/core/crypto/tls_connection.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/common/platform/api/quiche_export.h" namespace quic { @@ -120,6 +129,10 @@ class QUICHE_EXPORT TlsServerConnection : public TlsConnection { // Creates and configures an SSL_CTX that is appropriate for servers to use. static bssl::UniquePtr CreateSslCtx(ProofSource* proof_source); + // Invoke |configure_ssl| to configure the SSL object. + absl::Status ConfigureSSL( + ProofSourceHandleCallback::ConfigureSSLFunc configure_ssl); + void SetCertChain(const std::vector& cert_chain); // Set the client cert mode to be used on this connection. This should be diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc index df4d9d3bcb..b0bf32913a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.cc @@ -5,7 +5,9 @@ #include "quiche/quic/core/frames/quic_frame.h" #include "quiche/quic/core/frames/quic_new_connection_id_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h" +#include "quiche/quic/core/frames/quic_rst_stream_frame.h" #include "quiche/quic/core/quic_constants.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" @@ -80,6 +82,9 @@ QuicFrame::QuicFrame(QuicNewTokenFrame* frame) QuicFrame::QuicFrame(QuicAckFrequencyFrame* frame) : type(ACK_FREQUENCY_FRAME), ack_frequency_frame(frame) {} +QuicFrame::QuicFrame(QuicResetStreamAtFrame* frame) + : type(RESET_STREAM_AT_FRAME), reset_stream_at_frame(frame) {} + void DeleteFrames(QuicFrames* frames) { for (QuicFrame& frame : *frames) { DeleteFrame(&frame); @@ -148,6 +153,9 @@ void DeleteFrame(QuicFrame* frame) { case ACK_FREQUENCY_FRAME: delete frame->ack_frequency_frame; break; + case RESET_STREAM_AT_FRAME: + delete frame->reset_stream_at_frame; + break; case NUM_FRAME_TYPES: QUICHE_DCHECK(false) << "Cannot delete type: " << frame->type; } @@ -179,6 +187,7 @@ bool IsControlFrame(QuicFrameType type) { case HANDSHAKE_DONE_FRAME: case ACK_FREQUENCY_FRAME: case NEW_TOKEN_FRAME: + case RESET_STREAM_AT_FRAME: return true; default: return false; @@ -213,6 +222,8 @@ QuicControlFrameId GetControlFrameId(const QuicFrame& frame) { return frame.ack_frequency_frame->control_frame_id; case NEW_TOKEN_FRAME: return frame.new_token_frame->control_frame_id; + case RESET_STREAM_AT_FRAME: + return frame.reset_stream_at_frame->control_frame_id; default: return kInvalidControlFrameId; } @@ -259,6 +270,9 @@ void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) { case NEW_TOKEN_FRAME: frame->new_token_frame->control_frame_id = control_frame_id; return; + case RESET_STREAM_AT_FRAME: + frame->reset_stream_at_frame->control_frame_id = control_frame_id; + return; default: QUIC_BUG(quic_bug_12594_1) << "Try to set control frame id of a frame without control frame id"; @@ -310,6 +324,10 @@ QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) { case NEW_TOKEN_FRAME: copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame)); break; + case RESET_STREAM_AT_FRAME: + copy = + QuicFrame(new QuicResetStreamAtFrame(*frame.reset_stream_at_frame)); + break; default: QUIC_BUG(quic_bug_10533_1) << "Try to copy a non-retransmittable control frame: " << frame; @@ -404,6 +422,10 @@ QuicFrame CopyQuicFrame(quiche::QuicheBufferAllocator* allocator, case ACK_FREQUENCY_FRAME: copy = QuicFrame(new QuicAckFrequencyFrame(*frame.ack_frequency_frame)); break; + case RESET_STREAM_AT_FRAME: + copy = + QuicFrame(new QuicResetStreamAtFrame(*frame.reset_stream_at_frame)); + break; default: QUIC_BUG(quic_bug_10533_2) << "Cannot copy frame: " << frame; copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId)); @@ -506,6 +528,9 @@ std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) { case ACK_FREQUENCY_FRAME: os << "type { ACK_FREQUENCY_FRAME } " << *(frame.ack_frequency_frame); break; + case RESET_STREAM_AT_FRAME: + os << "type { RESET_STREAM_AT_FRAME } " << *(frame.reset_stream_at_frame); + break; default: { QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type; break; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h index 289b08d4c6..dc99fc4800 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_frame.h @@ -5,9 +5,10 @@ #ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_FRAME_H_ #define QUICHE_QUIC_CORE_FRAMES_QUIC_FRAME_H_ +#include #include +#include #include -#include #include "absl/container/inlined_vector.h" #include "quiche/quic/core/frames/quic_ack_frame.h" @@ -26,6 +27,7 @@ #include "quiche/quic/core/frames/quic_path_challenge_frame.h" #include "quiche/quic/core/frames/quic_path_response_frame.h" #include "quiche/quic/core/frames/quic_ping_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h" #include "quiche/quic/core/frames/quic_rst_stream_frame.h" #include "quiche/quic/core/frames/quic_stop_sending_frame.h" @@ -34,7 +36,8 @@ #include "quiche/quic/core/frames/quic_streams_blocked_frame.h" #include "quiche/quic/core/frames/quic_window_update_frame.h" #include "quiche/quic/core/quic_types.h" -#include "quiche/quic/platform/api/quic_export.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/common/quiche_buffer_allocator.h" #ifndef QUIC_FRAME_DEBUG #if !defined(NDEBUG) || defined(ADDRESS_SANITIZER) @@ -73,6 +76,7 @@ struct QUICHE_EXPORT QuicFrame { explicit QuicFrame(QuicMessageFrame* message_frame); explicit QuicFrame(QuicCryptoFrame* crypto_frame); explicit QuicFrame(QuicAckFrequencyFrame* ack_frequency_frame); + explicit QuicFrame(QuicResetStreamAtFrame* reset_stream_at_frame); QUICHE_EXPORT friend std::ostream& operator<<(std::ostream& os, const QuicFrame& frame); @@ -115,6 +119,7 @@ struct QUICHE_EXPORT QuicFrame { QuicCryptoFrame* crypto_frame; QuicAckFrequencyFrame* ack_frequency_frame; QuicNewTokenFrame* new_token_frame; + QuicResetStreamAtFrame* reset_stream_at_frame; }; }; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.cc new file mode 100644 index 0000000000..c8009c5385 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.cc @@ -0,0 +1,44 @@ +// Copyright 2024 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 "quiche/quic/core/frames/quic_reset_stream_at_frame.h" + +#include +#include + +#include "quiche/quic/core/quic_types.h" + +namespace quic { + +QuicResetStreamAtFrame::QuicResetStreamAtFrame( + QuicControlFrameId control_frame_id, QuicStreamId stream_id, uint64_t error, + QuicStreamOffset final_offset, QuicStreamOffset reliable_offset) + : control_frame_id(control_frame_id), + stream_id(stream_id), + error(error), + final_offset(final_offset), + reliable_offset(reliable_offset) {} + +std::ostream& operator<<(std::ostream& os, + const QuicResetStreamAtFrame& frame) { + os << "{ control_frame_id: " << frame.control_frame_id + << ", stream_id: " << frame.stream_id << ", error_code: " << frame.error + << ", final_offset: " << frame.final_offset + << ", reliable_offset: " << frame.reliable_offset << " }\n"; + return os; +} + +bool QuicResetStreamAtFrame::operator==( + const QuicResetStreamAtFrame& rhs) const { + return control_frame_id == rhs.control_frame_id && + stream_id == rhs.stream_id && error == rhs.error && + final_offset == rhs.final_offset && + reliable_offset == rhs.reliable_offset; +} +bool QuicResetStreamAtFrame::operator!=( + const QuicResetStreamAtFrame& rhs) const { + return !(*this == rhs); +} + +} // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.h new file mode 100644 index 0000000000..95e7ee99f1 --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/frames/quic_reset_stream_at_frame.h @@ -0,0 +1,49 @@ +// Copyright 2024 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. + +#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_RESET_STREAM_AT_FRAME_H_ +#define QUICHE_QUIC_CORE_FRAMES_QUIC_RESET_STREAM_AT_FRAME_H_ + +#include +#include + +#include "quiche/quic/core/quic_constants.h" +#include "quiche/quic/core/quic_types.h" +#include "quiche/common/platform/api/quiche_export.h" + +namespace quic { + +// RESET_STREAM_AT allows a QUIC application to reset a stream, but only after +// the receiver consumes data up to a certain point. Defined in +// . +struct QUICHE_EXPORT QuicResetStreamAtFrame { + QuicResetStreamAtFrame() = default; + QuicResetStreamAtFrame(QuicControlFrameId control_frame_id, + QuicStreamId stream_id, uint64_t error, + QuicStreamOffset final_offset, + QuicStreamOffset reliable_offset); + + friend QUICHE_EXPORT std::ostream& operator<<( + std::ostream& os, const QuicResetStreamAtFrame& frame); + + bool operator==(const QuicResetStreamAtFrame& rhs) const; + bool operator!=(const QuicResetStreamAtFrame& rhs) const; + + // A unique identifier of this control frame. 0 when this frame is received, + // and non-zero when sent. + QuicControlFrameId control_frame_id = kInvalidControlFrameId; + + QuicStreamId stream_id = 0; + uint64_t error = 0; + + // The total number of bytes ever sent on the stream; used for flow control. + QuicStreamOffset final_offset = 0; + // The RESET_STREAM is active only after the application reads up to + // `reliable_offset` bytes. + QuicStreamOffset reliable_offset = 0; +}; + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_RESET_STREAM_AT_FRAME_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h index 874dc102fb..5b72bb03bc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/http_frames.h @@ -108,7 +108,7 @@ struct QUICHE_EXPORT GoAwayFrame { // incoming 0xf0701 frames are treated as frames of unknown type. // Length of a priority frame's first byte. -const QuicByteCount kPriorityFirstByteLength = 1; +inline constexpr QuicByteCount kPriorityFirstByteLength = 1; struct QUICHE_EXPORT PriorityUpdateFrame { uint64_t prioritized_element_id = 0; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc index 816f21c94b..7d3a895820 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_stream.cc @@ -130,18 +130,6 @@ void QuicSpdyClientStream::OnTrailingHeadersComplete( } void QuicSpdyClientStream::OnBodyAvailable() { - const bool skip_return_on_null_visitor = - GetQuicReloadableFlag(quic_skip_return_on_null_visitor); - if (skip_return_on_null_visitor) { - QUICHE_RELOADABLE_FLAG_COUNT(quic_skip_return_on_null_visitor); - } - if (visitor() == nullptr) { - QUICHE_CODE_COUNT(quic_spdy_client_stream_visitor_null_on_body_available); - if (!skip_return_on_null_visitor) { - return; - } - } - while (HasBytesToRead()) { struct iovec iov; if (GetReadableRegions(&iov, 1) == 0) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc index d88951a81a..48c363a614 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.cc @@ -522,7 +522,7 @@ void QuicSpdySession::Initialize() { headers_stream_ = headers_stream.get(); ActivateStream(std::move(headers_stream)); } else { - qpack_encoder_ = std::make_unique(this); + qpack_encoder_ = std::make_unique(this, huffman_encoding_); qpack_decoder_ = std::make_unique(qpack_maximum_dynamic_table_capacity_, qpack_maximum_blocked_streams_, this); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h index 4c01b18142..2e614e1179 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_session.h @@ -284,6 +284,10 @@ class QUICHE_EXPORT QuicSpdySession qpack_maximum_dynamic_table_capacity; } + uint64_t qpack_maximum_dynamic_table_capacity() const { + return qpack_maximum_dynamic_table_capacity_; + } + // Must not be called after Initialize(). // TODO(bnc): Move to constructor argument. void set_qpack_maximum_blocked_streams( @@ -555,6 +559,11 @@ class QUICHE_EXPORT QuicSpdySession // is always bundled opportunistically. bool CheckStreamWriteBlocked(QuicStream* stream) const override; + // Disables the use of Huffman encoding for QPACK headers. + void DisableHuffmanEncoding() { + huffman_encoding_ = HuffmanEncoding::kDisabled; + } + private: friend class test::QuicSpdySessionPeer; @@ -602,6 +611,7 @@ class QUICHE_EXPORT QuicSpdySession bool ValidateWebTransportSettingsConsistency(); + HuffmanEncoding huffman_encoding_ = HuffmanEncoding::kEnabled; std::unique_ptr qpack_encoder_; std::unique_ptr qpack_decoder_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc index c38f6b0675..64757bca0a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_stream.cc @@ -315,9 +315,9 @@ void QuicSpdyStream::WriteOrBufferBody(absl::string_view data, bool fin) { QUICHE_DCHECK(success); // Write body. - QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id() - << " is writing DATA frame payload of length " - << data.length() << " with fin " << fin; + QUIC_DVLOG(1) << ENDPOINT << "Stream " << id() + << " is writing DATA frame payload of length " << data.length() + << " with fin " << fin; WriteOrBufferData(data, fin, nullptr); } @@ -336,8 +336,8 @@ size_t QuicSpdyStream::WriteTrailers( // trailers may be processed out of order at the peer. const QuicStreamOffset final_offset = stream_bytes_written() + BufferedDataBytes(); - QUIC_DLOG(INFO) << ENDPOINT << "Inserting trailer: (" - << kFinalOffsetHeaderKey << ", " << final_offset << ")"; + QUIC_DVLOG(1) << ENDPOINT << "Inserting trailer: (" << kFinalOffsetHeaderKey + << ", " << final_offset << ")"; trailer_block.insert( std::make_pair(kFinalOffsetHeaderKey, absl::StrCat(final_offset))); } @@ -391,9 +391,8 @@ bool QuicSpdyStream::WriteDataFrameHeader(QuicByteCount data_length, unacked_frame_headers_offsets_.Add( send_buffer().stream_offset(), send_buffer().stream_offset() + header.size()); - QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id() - << " is writing DATA frame header of length " - << header.size(); + QUIC_DVLOG(1) << ENDPOINT << "Stream " << id() + << " is writing DATA frame header of length " << header.size(); if (can_write) { // Save one copy and allocation if send buffer can accomodate the header. quiche::QuicheMemSlice header_slice(std::move(header)); @@ -417,8 +416,8 @@ QuicConsumedData QuicSpdyStream::WriteBodySlices( return {0, false}; } - QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id() - << " is writing DATA frame payload of length " << data_size; + QUIC_DVLOG(1) << ENDPOINT << "Stream " << id() + << " is writing DATA frame payload of length " << data_size; return WriteMemSlices(slices, fin); } @@ -1223,10 +1222,10 @@ size_t QuicSpdyStream::WriteHeadersImpl( send_buffer().stream_offset(), send_buffer().stream_offset() + headers_frame_header.length()); - QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id() - << " is writing HEADERS frame header of length " - << headers_frame_header.length() << ", and payload of length " - << encoded_headers.length() << " with fin " << fin; + QUIC_DVLOG(1) << ENDPOINT << "Stream " << id() + << " is writing HEADERS frame header of length " + << headers_frame_header.length() << ", and payload of length " + << encoded_headers.length() << " with fin " << fin; WriteOrBufferData(absl::StrCat(headers_frame_header, encoded_headers), fin, /*ack_listener=*/nullptr); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc index ff2faba10b..de21723ddb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/http/web_transport_stream_adapter.cc @@ -65,7 +65,9 @@ absl::Status WebTransportStreamAdapter::Writev( "Writev() called without any data or a FIN"); } const absl::Status initial_check_status = CheckBeforeStreamWrite(); - if (!initial_check_status.ok()) { + if (!initial_check_status.ok() && + !(initial_check_status.code() == absl::StatusCode::kUnavailable && + options.buffer_unconditionally())) { return initial_check_status; } @@ -82,8 +84,9 @@ absl::Status WebTransportStreamAdapter::Writev( iovecs.data(), iovecs.size(), session_->connection()->helper()->GetStreamSendBufferAllocator(), GetQuicFlag(quic_send_buffer_max_data_slice_size)); - QuicConsumedData consumed = - stream_->WriteMemSlices(storage.ToSpan(), /*fin=*/options.send_fin()); + QuicConsumedData consumed = stream_->WriteMemSlices( + storage.ToSpan(), /*fin=*/options.send_fin(), + /*buffer_uncondtionally=*/options.buffer_unconditionally()); if (consumed.bytes_consumed == total_size) { return absl::OkStatus(); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc index 3be61cb5f2..da33bd3901 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_decoder_stream_sender.cc @@ -16,7 +16,11 @@ namespace quic { -QpackDecoderStreamSender::QpackDecoderStreamSender() : delegate_(nullptr) {} +QpackDecoderStreamSender::QpackDecoderStreamSender() + : delegate_(nullptr), + // None of the instructions sent by the QpackDecoderStreamSender + // are strings, so huffman encoding is not relevant. + instruction_encoder_(HuffmanEncoding::kEnabled) {} void QpackDecoderStreamSender::SendInsertCountIncrement(uint64_t increment) { instruction_encoder_.Encode( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc index 9ee52266a9..a4b48fe5c2 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.cc @@ -33,9 +33,12 @@ const float kDrainingFraction = 0.25; } // anonymous namespace QpackEncoder::QpackEncoder( - DecoderStreamErrorDelegate* decoder_stream_error_delegate) - : decoder_stream_error_delegate_(decoder_stream_error_delegate), + DecoderStreamErrorDelegate* decoder_stream_error_delegate, + HuffmanEncoding huffman_encoding) + : huffman_encoding_(huffman_encoding), + decoder_stream_error_delegate_(decoder_stream_error_delegate), decoder_stream_receiver_(this), + encoder_stream_sender_(huffman_encoding), maximum_blocked_streams_(0), header_list_count_(0) { QUICHE_DCHECK(decoder_stream_error_delegate_); @@ -346,7 +349,7 @@ QpackEncoder::Representations QpackEncoder::FirstPassEncode( std::string QpackEncoder::SecondPassEncode( QpackEncoder::Representations representations, uint64_t required_insert_count) const { - QpackInstructionEncoder instruction_encoder; + QpackInstructionEncoder instruction_encoder(huffman_encoding_); std::string encoded_headers; // Header block prefix. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h index bb34b2002b..0c2ffbf1fc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder.h @@ -44,7 +44,8 @@ class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { absl::string_view error_message) = 0; }; - QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate); + QpackEncoder(DecoderStreamErrorDelegate* decoder_stream_error_delegate, + HuffmanEncoding huffman_encoding); ~QpackEncoder() override; // Encode a header list. If |encoder_stream_sent_byte_count| is not null, @@ -145,6 +146,7 @@ class QUICHE_EXPORT QpackEncoder : public QpackDecoderStreamReceiver::Delegate { std::string SecondPassEncode(Representations representations, uint64_t required_insert_count) const; + const HuffmanEncoding huffman_encoding_; DecoderStreamErrorDelegate* const decoder_stream_error_delegate_; QpackDecoderStreamReceiver decoder_stream_receiver_; QpackEncoderStreamSender encoder_stream_sender_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc index 574b3bb939..2c25c22840 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.cc @@ -22,7 +22,9 @@ constexpr uint64_t kMaxBytesBufferedByStream = 64 * 1024; } // anonymous namespace -QpackEncoderStreamSender::QpackEncoderStreamSender() : delegate_(nullptr) {} +QpackEncoderStreamSender::QpackEncoderStreamSender( + HuffmanEncoding huffman_encoding) + : delegate_(nullptr), instruction_encoder_(huffman_encoding) {} void QpackEncoderStreamSender::SendInsertWithNameReference( bool is_static, uint64_t name_index, absl::string_view value) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.h index a8c0bbcf9d..958da7eefa 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_encoder_stream_sender.h @@ -19,7 +19,7 @@ namespace quic { // Serialized instructions are buffered until Flush() is called. class QUICHE_EXPORT QpackEncoderStreamSender { public: - QpackEncoderStreamSender(); + QpackEncoderStreamSender(HuffmanEncoding huffman_encoding); QpackEncoderStreamSender(const QpackEncoderStreamSender&) = delete; QpackEncoderStreamSender& operator=(const QpackEncoderStreamSender&) = delete; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc index 21f549ccf9..60876d64de 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.cc @@ -15,8 +15,10 @@ namespace quic { -QpackInstructionEncoder::QpackInstructionEncoder() - : use_huffman_(false), +QpackInstructionEncoder::QpackInstructionEncoder( + HuffmanEncoding huffman_encoding) + : huffman_encoding_(huffman_encoding), + use_huffman_(false), string_length_(0), byte_(0), state_(State::kOpcode), @@ -142,16 +144,17 @@ void QpackInstructionEncoder::DoStartString(absl::string_view name, (field_->type == QpackInstructionFieldType::kName) ? name : value; string_length_ = string_to_write.size(); - size_t encoded_size = http2::HuffmanSize(string_to_write); - use_huffman_ = encoded_size < string_length_; + if (huffman_encoding_ == HuffmanEncoding::kEnabled) { + size_t encoded_size = http2::HuffmanSize(string_to_write); + use_huffman_ = encoded_size < string_length_; - if (use_huffman_) { - QUICHE_DCHECK_EQ(0, byte_ & (1 << field_->param)); - byte_ |= (1 << field_->param); + if (use_huffman_) { + QUICHE_DCHECK_EQ(0, byte_ & (1 << field_->param)); + byte_ |= (1 << field_->param); - string_length_ = encoded_size; + string_length_ = encoded_size; + } } - state_ = State::kVarintEncode; } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.h index 3d6003e659..37cd3d1327 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/qpack/qpack_instruction_encoder.h @@ -14,12 +14,19 @@ namespace quic { +// Enum which specifies if Huffman encoding should be used when sending +// QPACK headers. +enum class HuffmanEncoding { + kEnabled, + kDisabled, +}; + // Generic instruction encoder class. Takes a QpackLanguage that describes a // language, that is, a set of instruction opcodes together with a list of // fields that follow each instruction. class QUICHE_EXPORT QpackInstructionEncoder { public: - QpackInstructionEncoder(); + explicit QpackInstructionEncoder(HuffmanEncoding huffman_encoding); QpackInstructionEncoder(const QpackInstructionEncoder&) = delete; QpackInstructionEncoder& operator=(const QpackInstructionEncoder&) = delete; @@ -57,6 +64,10 @@ class QUICHE_EXPORT QpackInstructionEncoder { void DoWriteString(absl::string_view name, absl::string_view value, std::string* output); + // If true then Huffman encoding will not be used, regardless of the + // string size. + const HuffmanEncoding huffman_encoding_; + // True if name or value should be Huffman encoded. bool use_huffman_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc index 75d29f3d70..2516c8cd9c 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.cc @@ -1428,4 +1428,9 @@ void QuicConfig::ClearAlternateServerAddressToSend( } } +bool QuicConfig::SupportsServerPreferredAddress(Perspective perspective) const { + return HasClientSentConnectionOption(kSPAD, perspective) || + GetQuicFlag(quic_always_support_server_preferred_address); +} + } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h index bf1cc6c29f..c635689071 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_config.h @@ -418,6 +418,11 @@ class QUICHE_EXPORT QuicConfig { void ClearAlternateServerAddressToSend( quiche::IpAddressFamily address_family); + // Returns true if this config supports server preferred address, + // either via the kSPAD connection option or the QUIC protocol flag + // quic_always_support_server_preferred_address. + bool SupportsServerPreferredAddress(Perspective perspective) const; + // Original destination connection ID. void SetOriginalConnectionIdToSend( const QuicConnectionId& original_destination_connection_id); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc index 3a3b356aa2..99d88911c0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.cc @@ -648,7 +648,7 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) { if (version().HasIetfQuicFrames() && config.HasReceivedPreferredAddressConnectionIdAndToken() && - config.HasClientSentConnectionOption(kSPAD, perspective_)) { + config.SupportsServerPreferredAddress(perspective_)) { if (self_address().host().IsIPv4() && config.HasReceivedIPv4AlternateServerAddress()) { received_server_preferred_address_ = @@ -2120,6 +2120,25 @@ bool QuicConnection::OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) { return true; } +bool QuicConnection::OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) { + QUIC_BUG_IF(OnResetStreamAtFrame_connection_closed, !connected_) + << "Processing RESET_STREAM_AT frame while the connection is closed. " + "Received packet info: " + << last_received_packet_info_; + + if (debug_visitor_ != nullptr) { + debug_visitor_->OnResetStreamAtFrame(frame); + } + if (!UpdatePacketContent(RESET_STREAM_AT_FRAME)) { + return false; + } + + // TODO(b/278878322): implement. + + MaybeUpdateAckTimeout(); + return true; +} + bool QuicConnection::OnBlockedFrame(const QuicBlockedFrame& frame) { QUIC_BUG_IF(quic_bug_12714_17, !connected_) << "Processing BLOCKED frame when connection is closed. Received packet " @@ -5705,8 +5724,23 @@ QuicPacketLength QuicConnection::GetGuaranteedLargestMessagePayload() const { uint32_t QuicConnection::cipher_id() const { if (version().KnowsWhichDecrypterToUse()) { - return framer_.GetDecrypter(last_received_packet_info_.decrypted_level) - ->cipher_id(); + if (quic_limit_new_streams_per_loop_2_) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_limit_new_streams_per_loop_2, 4, 4); + for (auto decryption_level : + {ENCRYPTION_FORWARD_SECURE, ENCRYPTION_HANDSHAKE, + ENCRYPTION_ZERO_RTT, ENCRYPTION_INITIAL}) { + const QuicDecrypter* decrypter = framer_.GetDecrypter(decryption_level); + if (decrypter != nullptr) { + return decrypter->cipher_id(); + } + } + QUICHE_BUG(no_decrypter_found) + << ENDPOINT << "No decrypter found at all encryption levels"; + return 0; + } else { + return framer_.GetDecrypter(last_received_packet_info_.decrypted_level) + ->cipher_id(); + } } return framer_.decrypter()->cipher_id(); } @@ -6670,6 +6704,10 @@ void QuicConnection::ValidatePath( context->peer_address(), client_connection_id, server_connection_id, stateless_reset_token); } + if (multi_port_stats_ != nullptr && + reason == PathValidationReason::kMultiPort) { + multi_port_stats_->num_client_probing_attempts++; + } path_validator_.StartPathValidation(std::move(context), std::move(result_delegate), reason); if (perspective_ == Perspective::IS_CLIENT && @@ -7097,6 +7135,7 @@ void QuicConnection::OnMultiPortPathProbingSuccess( multi_port_probing_alarm_->Set(clock_->ApproximateNow() + multi_port_probing_interval_); if (multi_port_stats_ != nullptr) { + multi_port_stats_->num_successful_probes++; auto now = clock_->Now(); auto time_delta = now - start_time; multi_port_stats_->rtt_stats.UpdateRtt(time_delta, QuicTime::Delta::Zero(), @@ -7119,6 +7158,9 @@ void QuicConnection::MaybeProbeMultiPortPath() { multi_port_probing_alarm_->IsSet()) { return; } + if (multi_port_stats_ != nullptr) { + multi_port_stats_->num_client_probing_attempts++; + } auto multi_port_validation_result_delegate = std::make_unique(this); path_validator_.StartPathValidation( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h index 14033bd222..5a770be5ba 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection.h @@ -34,6 +34,7 @@ #include "quiche/quic/core/frames/quic_ack_frequency_frame.h" #include "quiche/quic/core/frames/quic_max_streams_frame.h" #include "quiche/quic/core/frames/quic_new_connection_id_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_alarm.h" #include "quiche/quic/core/quic_alarm_factory.h" #include "quiche/quic/core/quic_blocked_writer_interface.h" @@ -424,6 +425,9 @@ class QUICHE_EXPORT QuicConnectionDebugVisitor // Called when an AckFrequencyFrame has been parsed. virtual void OnAckFrequencyFrame(const QuicAckFrequencyFrame& /*frame*/) {} + // Called when a ResetStreamAtFrame has been parsed. + virtual void OnResetStreamAtFrame(const QuicResetStreamAtFrame& /*frame*/) {} + // Called when |count| packet numbers have been skipped. virtual void OnNPacketNumbersSkipped(QuicPacketCount /*count*/, QuicTime /*now*/) {} @@ -517,6 +521,10 @@ class QUICHE_EXPORT QuicConnection size_t num_multi_port_probe_failures_when_path_degrading = 0; // number of total multi-port path creations in a connection size_t num_multi_port_paths_created = 0; + // number of client probing attempts. + size_t num_client_probing_attempts = 0; + // number of successful probes. + size_t num_successful_probes = 0; }; // Sets connection parameters from the supplied |config|. @@ -713,6 +721,7 @@ class QUICHE_EXPORT QuicConnection bool OnMessageFrame(const QuicMessageFrame& frame) override; bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override; bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override; + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override; void OnPacketComplete() override; bool IsValidStatelessResetToken( const StatelessResetToken& token) const override; @@ -1343,6 +1352,10 @@ class QUICHE_EXPORT QuicConnection return packet_writer_params_.ecn_codepoint; } + bool quic_limit_new_streams_per_loop_2() const { + return quic_limit_new_streams_per_loop_2_; + } + protected: // Calls cancel() on all the alarms owned by this connection. void CancelAllAlarms(); @@ -2413,6 +2426,9 @@ class QUICHE_EXPORT QuicConnection // The ECN codepoint of the last packet to be sent to the writer, which // might be different from the next codepoint in per_packet_options_. QuicEcnCodepoint last_ecn_codepoint_sent_ = ECN_NOT_ECT; + + const bool quic_limit_new_streams_per_loop_2_ = + GetQuicReloadableFlag(quic_limit_new_streams_per_loop_2); }; } // namespace quic diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h index 6bf5cc41b8..b7f8b48d92 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_connection_id.h @@ -23,19 +23,19 @@ enum QuicConnectionIdIncluded : uint8_t { // Maximum connection ID length supported by versions that use the encoding from // draft-ietf-quic-invariants-06. -const uint8_t kQuicMaxConnectionIdWithLengthPrefixLength = 20; +inline constexpr uint8_t kQuicMaxConnectionIdWithLengthPrefixLength = 20; // Maximum connection ID length supported by versions that use the encoding from // draft-ietf-quic-invariants-05. -const uint8_t kQuicMaxConnectionId4BitLength = 18; +inline constexpr uint8_t kQuicMaxConnectionId4BitLength = 18; // kQuicDefaultConnectionIdLength is the only supported length for QUIC // versions < v99, and is the default picked for all versions. -const uint8_t kQuicDefaultConnectionIdLength = 8; +inline constexpr uint8_t kQuicDefaultConnectionIdLength = 8; // According to the IETF spec, the initial server connection ID generated by // the client must be at least this long. -const uint8_t kQuicMinimumInitialConnectionIdLength = 8; +inline constexpr uint8_t kQuicMinimumInitialConnectionIdLength = 8; class QUICHE_EXPORT QuicConnectionId { public: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h index bbf4aebbb1..10790c519f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flags_list.h @@ -73,12 +73,10 @@ QUIC_FLAG(quic_reloadable_flag_quic_enable_disable_resumption, true) QUIC_FLAG(quic_reloadable_flag_quic_discard_initial_packet_with_key_dropped, true) // If true, dispatcher sends error code QUIC_HANDSHAKE_FAILED_PACKETS_BUFFERED_TOO_LONG when handshake fails due to packets buffered for too long. QUIC_FLAG(quic_reloadable_flag_quic_new_error_code_when_packets_buffered_too_long, true) -// If true, do not return from QuicSpdyClientStream::OnBodyAvailable() if visitor is nullptr. -QUIC_FLAG(quic_reloadable_flag_quic_skip_return_on_null_visitor, true) // If true, enable server retransmittable on wire PING. QUIC_FLAG(quic_reloadable_flag_quic_enable_server_on_wire_ping, true) // If true, fix a QUIC BBR2 bytes counting issue caused by spurious losses. -QUIC_FLAG(quic_reloadable_flag_quic_bbr2_fix_spurious_loss_bytes_counting, false) +QUIC_FLAG(quic_reloadable_flag_quic_bbr2_fix_spurious_loss_bytes_counting, true) // If true, include stream information in idle timeout connection close detail. QUIC_FLAG(quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true) // If true, reject or send error response code upon receiving invalid request or response headers. @@ -101,14 +99,14 @@ QUIC_FLAG(quic_reloadable_flag_quic_use_received_client_addresses_cache, true) QUIC_FLAG(quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false) // If true, when TicketCrypter fails to encrypt a session ticket, quic::TlsServerHandshaker will send a placeholder ticket, instead of an empty one, to the client. QUIC_FLAG(quic_reloadable_flag_quic_send_placeholder_ticket_when_encrypt_ticket_fails, true) +// If true, when the peer sends connection options \\\\\\\'SLP1\\\\\\\', \\\\\\\'SLP2\\\\\\\' and \\\\\\\'SLPF\\\\\\\', internet facing GFEs will only allow a limited number of new requests to be processed per event loop, and postpone the rest to the following event loops. Also guard QuicConnection to iterate through all decrypters at each encryption level to get cipher id for a request. +QUIC_FLAG(quic_reloadable_flag_quic_limit_new_streams_per_loop_2, false) // When true, allows sending of QUIC packets marked ECT(1). A different flag (TBD) will actually utilize this capability to send ECT(1). QUIC_FLAG(quic_restart_flag_quic_support_ect1, false) // When true, correctly stores the ECN mark on incoming packets when buffered while waiting for a crypto context. -QUIC_FLAG(quic_reloadable_flag_quic_clone_ecn, false) +QUIC_FLAG(quic_reloadable_flag_quic_clone_ecn, true) // When true, defaults to BBR congestion control instead of Cubic. QUIC_FLAG(quic_reloadable_flag_quic_default_to_bbr, false) -// When true, report received ECN markings to the peer. Replaces quic_receive_ecn2 to use correct codepoints. -QUIC_FLAG(quic_restart_flag_quic_receive_ecn3, true) // When true, support RFC9369. QUIC_FLAG(quic_reloadable_flag_quic_enable_version_rfcv2, false) // When true, the BB2U copt causes BBR2 to wait two rounds with out draining the queue before exiting PROBE_UP and BB2S has the same effect in STARTUP. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h index 8bd43c2a0a..6091f59ce7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_flow_controller.h @@ -19,7 +19,7 @@ class QuicSession; // How much larger the session flow control window needs to be relative to any // stream's flow control window. -const float kSessionFlowControlMultiplier = 1.5; +inline constexpr float kSessionFlowControlMultiplier = 1.5; class QUICHE_EXPORT QuicFlowControllerInterface { public: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc index 8f3a736d53..d4bb1bcdaa 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.cc @@ -19,6 +19,7 @@ #include "absl/base/macros.h" #include "absl/base/optimization.h" #include "absl/cleanup/cleanup.h" +#include "absl/status/status.h" #include "absl/strings/escaping.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" @@ -35,6 +36,7 @@ #include "quiche/quic/core/crypto/quic_encrypter.h" #include "quiche/quic/core/crypto/quic_random.h" #include "quiche/quic/core/frames/quic_ack_frequency_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_connection_context.h" #include "quiche/quic/core/quic_connection_id.h" #include "quiche/quic/core/quic_constants.h" @@ -56,6 +58,7 @@ #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_stack_trace.h" #include "quiche/common/quiche_text_utils.h" +#include "quiche/common/wire_serialization.h" namespace quic { @@ -401,6 +404,7 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions, process_timestamps_(false), max_receive_timestamps_per_ack_(std::numeric_limits::max()), receive_timestamps_exponent_(0), + process_reset_stream_at_(false), creation_time_(creation_time), last_timestamp_(QuicTime::Delta::Zero()), support_key_update_for_connection_(false), @@ -624,6 +628,16 @@ size_t QuicFramer::GetAckFrequencyFrameSize( 1; } +// static +size_t QuicFramer::GetResetStreamAtFrameSize( + const QuicResetStreamAtFrame& frame) { + return QuicDataWriter::GetVarInt62Len(IETF_RESET_STREAM_AT) + + QuicDataWriter::GetVarInt62Len(frame.stream_id) + + QuicDataWriter::GetVarInt62Len(frame.error) + + QuicDataWriter::GetVarInt62Len(frame.final_offset) + + QuicDataWriter::GetVarInt62Len(frame.reliable_offset); +} + // static size_t QuicFramer::GetPathChallengeFrameSize( const QuicPathChallengeFrame& frame) { @@ -679,6 +693,8 @@ size_t QuicFramer::GetRetransmittableControlFrameSize( return kQuicFrameTypeSize; case ACK_FREQUENCY_FRAME: return GetAckFrequencyFrameSize(*frame.ack_frequency_frame); + case RESET_STREAM_AT_FRAME: + return GetResetStreamAtFrameSize(*frame.reset_stream_at_frame); case STREAM_FRAME: case ACK_FRAME: case STOP_WAITING_FRAME: @@ -1193,6 +1209,17 @@ size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames, return 0; } break; + case RESET_STREAM_AT_FRAME: + QUIC_BUG_IF(reset_stream_at_appended_while_disabled, + !process_reset_stream_at_) + << "Requested serialization of RESET_STREAM_AT_FRAME while it is " + "not explicitly enabled in the framer"; + if (!AppendResetFrameAtFrame(*frame.reset_stream_at_frame, *writer)) { + QUIC_BUG(cannot_append_reset_stream_at) + << "AppendResetStreamAtFram failed: " << detailed_error(); + return 0; + } + break; default: set_detailed_error("Tried to append unknown frame type."); RaiseError(QUIC_INVALID_FRAME_DATA); @@ -3126,6 +3153,24 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader, } break; } + case IETF_RESET_STREAM_AT: { + if (!process_reset_stream_at_) { + set_detailed_error("RESET_STREAM_AT not enabled."); + return RaiseError(QUIC_INVALID_FRAME_DATA); + } + QuicResetStreamAtFrame frame; + if (!ProcessResetStreamAtFrame(*reader, frame)) { + return RaiseError(QUIC_INVALID_FRAME_DATA); + } + QUIC_DVLOG(2) << ENDPOINT << "Processing RESET_STREAM_AT frame " + << frame; + if (!visitor_->OnResetStreamAtFrame(frame)) { + QUIC_DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; + } + break; + } default: set_detailed_error("Illegal frame type."); QUIC_DLOG(WARNING) @@ -3345,6 +3390,31 @@ bool QuicFramer::ProcessAckFrequencyFrame(QuicDataReader* reader, return true; } +bool QuicFramer::ProcessResetStreamAtFrame(QuicDataReader& reader, + QuicResetStreamAtFrame& frame) { + if (!ReadUint32FromVarint62(&reader, IETF_RESET_STREAM_AT, + &frame.stream_id)) { + return false; + } + if (!reader.ReadVarInt62(&frame.error)) { + set_detailed_error("Failed to read the error code."); + return false; + } + if (!reader.ReadVarInt62(&frame.final_offset)) { + set_detailed_error("Failed to read the final offset."); + return false; + } + if (!reader.ReadVarInt62(&frame.reliable_offset)) { + set_detailed_error("Failed to read the reliable offset."); + return false; + } + if (frame.reliable_offset > frame.final_offset) { + set_detailed_error("reliable_offset > final_offset"); + return false; + } + return true; +} + bool QuicFramer::ProcessAckFrame(QuicDataReader* reader, uint8_t frame_type) { const bool has_ack_blocks = ExtractBit(frame_type, kQuicHasMultipleAckBlocksOffset); @@ -4951,6 +5021,9 @@ bool QuicFramer::AppendIetfFrameType(const QuicFrame& frame, case ACK_FREQUENCY_FRAME: type_byte = IETF_ACK_FREQUENCY; break; + case RESET_STREAM_AT_FRAME: + type_byte = IETF_RESET_STREAM_AT; + break; default: QUIC_BUG(quic_bug_10850_75) << "Attempt to generate a frame type for an unsupported value: " @@ -5194,6 +5267,26 @@ bool QuicFramer::AppendAckFrequencyFrame(const QuicAckFrequencyFrame& frame, return true; } +bool QuicFramer::AppendResetFrameAtFrame(const QuicResetStreamAtFrame& frame, + QuicDataWriter& writer) { + if (frame.reliable_offset > frame.final_offset) { + QUIC_BUG(AppendResetFrameAtFrame_offset_mismatch) + << "reliable_offset > final_offset"; + set_detailed_error("reliable_offset > final_offset"); + return false; + } + absl::Status status = + quiche::SerializeIntoWriter(writer, quiche::WireVarInt62(frame.stream_id), + quiche::WireVarInt62(frame.error), + quiche::WireVarInt62(frame.final_offset), + quiche::WireVarInt62(frame.reliable_offset)); + if (!status.ok()) { + set_detailed_error(std::string(status.message())); + return false; + } + return true; +} + void QuicFramer::set_version(const ParsedQuicVersion version) { QUICHE_DCHECK(IsSupportedVersion(version)) << ParsedQuicVersionToString(version); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h index 62c4ce817a..5e54bb1f8e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_framer.h @@ -15,6 +15,7 @@ #include "quiche/quic/core/crypto/quic_decrypter.h" #include "quiche/quic/core/crypto/quic_encrypter.h" #include "quiche/quic/core/crypto/quic_random.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_connection_id.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_types.h" @@ -32,37 +33,38 @@ class QuicFramer; class QuicStreamFrameDataProducer; // Number of bytes reserved for the frame type preceding each frame. -const size_t kQuicFrameTypeSize = 1; +inline constexpr size_t kQuicFrameTypeSize = 1; // Number of bytes reserved for error code. -const size_t kQuicErrorCodeSize = 4; +inline constexpr size_t kQuicErrorCodeSize = 4; // Number of bytes reserved to denote the length of error details field. -const size_t kQuicErrorDetailsLengthSize = 2; +inline constexpr size_t kQuicErrorDetailsLengthSize = 2; // Maximum number of bytes reserved for stream id. -const size_t kQuicMaxStreamIdSize = 4; +inline constexpr size_t kQuicMaxStreamIdSize = 4; // Maximum number of bytes reserved for byte offset in stream frame. -const size_t kQuicMaxStreamOffsetSize = 8; +inline constexpr size_t kQuicMaxStreamOffsetSize = 8; // Number of bytes reserved to store payload length in stream frame. -const size_t kQuicStreamPayloadLengthSize = 2; +inline constexpr size_t kQuicStreamPayloadLengthSize = 2; // Number of bytes to reserve for IQ Error codes (for the Connection Close, // Application Close, and Reset Stream frames). -const size_t kQuicIetfQuicErrorCodeSize = 2; +inline constexpr size_t kQuicIetfQuicErrorCodeSize = 2; // Minimum size of the IETF QUIC Error Phrase's length field -const size_t kIetfQuicMinErrorPhraseLengthSize = 1; +inline constexpr size_t kIetfQuicMinErrorPhraseLengthSize = 1; // Size in bytes reserved for the delta time of the largest observed // packet number in ack frames. -const size_t kQuicDeltaTimeLargestObservedSize = 2; +inline constexpr size_t kQuicDeltaTimeLargestObservedSize = 2; // Size in bytes reserved for the number of received packets with timestamps. -const size_t kQuicNumTimestampsSize = 1; +inline constexpr size_t kQuicNumTimestampsSize = 1; // Size in bytes reserved for the number of missing packets in ack frames. -const size_t kNumberOfNackRangesSize = 1; +inline constexpr size_t kNumberOfNackRangesSize = 1; // Size in bytes reserved for the number of ack blocks in ack frames. -const size_t kNumberOfAckBlocksSize = 1; +inline constexpr size_t kNumberOfAckBlocksSize = 1; // Maximum number of missing packet ranges that can fit within an ack frame. -const size_t kMaxNackRanges = (1 << (kNumberOfNackRangesSize * 8)) - 1; +inline constexpr size_t kMaxNackRanges = + (1 << (kNumberOfNackRangesSize * 8)) - 1; // Maximum number of ack blocks that can fit within an ack frame. -const size_t kMaxAckBlocks = (1 << (kNumberOfAckBlocksSize * 8)) - 1; +inline constexpr size_t kMaxAckBlocks = (1 << (kNumberOfAckBlocksSize * 8)) - 1; // This class receives callbacks from the framer when packets // are processed. @@ -221,6 +223,9 @@ class QUICHE_EXPORT QuicFramerVisitorInterface { // Called when an AckFrequencyFrame has been parsed. virtual bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) = 0; + // Called when an ResetStreamAtFrame has been parsed. + virtual bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) = 0; + // Called when a packet has been completely processed. virtual void OnPacketComplete() = 0; @@ -323,6 +328,11 @@ class QUICHE_EXPORT QuicFramer { receive_timestamps_exponent_ = exponent; } + // Allows enabling RESET_STREAM_AT frame processing. + void set_process_reset_stream_at(bool process_reset_stream_at) { + process_reset_stream_at_ = process_reset_stream_at; + } + // Pass a UDP packet into the framer for parsing. // Return true if the packet was processed successfully. |packet| must be a // single, complete UDP packet (not a frame of a packet). This packet @@ -359,6 +369,8 @@ class QUICHE_EXPORT QuicFramer { const QuicRstStreamFrame& frame); // Size in bytes of all ack frenquency frame fields. static size_t GetAckFrequencyFrameSize(const QuicAckFrequencyFrame& frame); + // Size in bytes of all RESET_STREAM_AT frame fields. + static size_t GetResetStreamAtFrameSize(const QuicResetStreamAtFrame& frame); // Size in bytes of all connection close frame fields, including the error // details. static size_t GetConnectionCloseFrameSize( @@ -538,6 +550,8 @@ class QUICHE_EXPORT QuicFramer { bool AppendCryptoFrame(const QuicCryptoFrame& frame, QuicDataWriter* writer); bool AppendAckFrequencyFrame(const QuicAckFrequencyFrame& frame, QuicDataWriter* writer); + bool AppendResetFrameAtFrame(const QuicResetStreamAtFrame& frame, + QuicDataWriter& writer); // SetDecrypter sets the primary decrypter, replacing any that already exists. // If an alternative decrypter is in place then the function QUICHE_DCHECKs. @@ -977,6 +991,8 @@ class QUICHE_EXPORT QuicFramer { QuicCryptoFrame* frame); bool ProcessAckFrequencyFrame(QuicDataReader* reader, QuicAckFrequencyFrame* frame); + bool ProcessResetStreamAtFrame(QuicDataReader& reader, + QuicResetStreamAtFrame& frame); // IETF frame appending methods. All methods append the type byte as well. bool AppendIetfStreamFrame(const QuicStreamFrame& frame, bool last_frame_in_packet, QuicDataWriter* writer); @@ -1111,6 +1127,8 @@ class QUICHE_EXPORT QuicFramer { mutable uint32_t max_receive_timestamps_per_ack_; // The exponent to use when writing/reading ACK receive timestamps. mutable uint32_t receive_timestamps_exponent_; + // If true, process RESET_STREAM_AT frames. + bool process_reset_stream_at_; // The creation time of the connection, used to calculate timestamps. QuicTime creation_time_; // The last timestamp received if process_timestamps_ is true. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h index 48d02f3735..384f0a3ad4 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_generic_session.h @@ -33,7 +33,7 @@ namespace quic { class QuicGenericStream; // Returns QUIC versions to be used with QuicGenericSessionBase. -ParsedQuicVersionVector GetQuicVersionsForGenericSession(); +QUICHE_EXPORT ParsedQuicVersionVector GetQuicVersionsForGenericSession(); using CreateWebTransportSessionVisitorCallback = quiche::UnretainedCallback( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h index a1e725b896..a0e338d4d7 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_linux_socket_utils.h @@ -44,20 +44,20 @@ namespace quic { -const int kCmsgSpaceForIpv4 = CMSG_SPACE(sizeof(in_pktinfo)); -const int kCmsgSpaceForIpv6 = CMSG_SPACE(sizeof(in6_pktinfo)); +inline constexpr int kCmsgSpaceForIpv4 = CMSG_SPACE(sizeof(in_pktinfo)); +inline constexpr int kCmsgSpaceForIpv6 = CMSG_SPACE(sizeof(in6_pktinfo)); // kCmsgSpaceForIp should be big enough to hold both IPv4 and IPv6 packet info. -const int kCmsgSpaceForIp = (kCmsgSpaceForIpv4 < kCmsgSpaceForIpv6) - ? kCmsgSpaceForIpv6 - : kCmsgSpaceForIpv4; +inline constexpr int kCmsgSpaceForIp = (kCmsgSpaceForIpv4 < kCmsgSpaceForIpv6) + ? kCmsgSpaceForIpv6 + : kCmsgSpaceForIpv4; -const int kCmsgSpaceForSegmentSize = CMSG_SPACE(sizeof(uint16_t)); +inline constexpr int kCmsgSpaceForSegmentSize = CMSG_SPACE(sizeof(uint16_t)); -const int kCmsgSpaceForTxTime = CMSG_SPACE(sizeof(uint64_t)); +inline constexpr int kCmsgSpaceForTxTime = CMSG_SPACE(sizeof(uint64_t)); -const int kCmsgSpaceForTTL = CMSG_SPACE(sizeof(int)); +inline constexpr int kCmsgSpaceForTTL = CMSG_SPACE(sizeof(int)); -const int kCmsgSpaceForTOS = CMSG_SPACE(sizeof(int)); +inline constexpr int kCmsgSpaceForTOS = CMSG_SPACE(sizeof(int)); // QuicMsgHdr is used to build msghdr objects that can be used send packets via // ::sendmsg. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.h index 68fbc6dafc..fe61640963 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_mtu_discovery.h @@ -14,10 +14,10 @@ namespace quic { // The initial number of packets between MTU probes. After each attempt the // number is doubled. -const QuicPacketCount kPacketsBetweenMtuProbesBase = 100; +inline constexpr QuicPacketCount kPacketsBetweenMtuProbesBase = 100; // The number of MTU probes that get sent before giving up. -const size_t kMtuDiscoveryAttempts = 3; +inline constexpr size_t kMtuDiscoveryAttempts = 3; // Ensure that exponential back-off does not result in an integer overflow. // The number of packets can be potentially capped, but that is not useful at @@ -28,8 +28,8 @@ static_assert(kPacketsBetweenMtuProbesBase < (1 << 8), "The initial number of packets between MTU probes is too high"); // The increased packet size targeted when doing path MTU discovery. -const QuicByteCount kMtuDiscoveryTargetPacketSizeHigh = 1400; -const QuicByteCount kMtuDiscoveryTargetPacketSizeLow = 1380; +inline constexpr QuicByteCount kMtuDiscoveryTargetPacketSizeHigh = 1400; +inline constexpr QuicByteCount kMtuDiscoveryTargetPacketSizeLow = 1380; static_assert(kMtuDiscoveryTargetPacketSizeLow <= kMaxOutgoingPacketSize, "MTU discovery target is too large"); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc index 1436ab5dc8..86062fdc55 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.cc @@ -53,11 +53,8 @@ bool QuicPacketReader::ReadAndDispatchPackets( {QuicUdpPacketInfoBit::DROPPED_PACKETS, QuicUdpPacketInfoBit::PEER_ADDRESS, QuicUdpPacketInfoBit::V4_SELF_IP, QuicUdpPacketInfoBit::V6_SELF_IP, QuicUdpPacketInfoBit::RECV_TIMESTAMP, - QuicUdpPacketInfoBit::TTL, QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER}); - if (GetQuicRestartFlag(quic_receive_ecn3)) { - QUIC_RESTART_FLAG_COUNT_N(quic_receive_ecn3, 2, 2); - info_bits.Set(QuicUdpPacketInfoBit::ECN); - } + QuicUdpPacketInfoBit::TTL, QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER, + QuicUdpPacketInfoBit::ECN}); size_t packets_read = socket_api_.ReadMultiplePackets(fd, info_bits, &read_results_); for (size_t i = 0; i < packets_read; ++i) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.h index c9945573fa..3b417f24bf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_packet_reader.h @@ -18,7 +18,7 @@ namespace quic { // Read in larger batches to minimize recvmmsg overhead. -const int kNumPacketsPerReadMmsgCall = 16; +inline constexpr int kNumPacketsPerReadMmsgCall = 16; class QUICHE_EXPORT QuicPacketReader { public: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h deleted file mode 100644 index bd337e9f76..0000000000 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_protocol_flags_list.h +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) 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. - -// NOLINT(build/header_guard) -// This file intentionally does not have header guards, it's intended to be -// included multiple times, each time with a different definition of -// QUIC_PROTOCOL_FLAG. - -#if defined(QUIC_PROTOCOL_FLAG) - -QUIC_PROTOCOL_FLAG( - bool, quic_allow_chlo_buffering, true, - "If true, allows packets to be buffered in anticipation of a " - "future CHLO, and allow CHLO packets to be buffered until next " - "iteration of the event loop.") - -QUIC_PROTOCOL_FLAG(bool, quic_disable_pacing_for_perf_tests, false, - "If true, disable pacing in QUIC") - -// Note that single-packet CHLOs are only enforced for Google QUIC versions that -// do not use CRYPTO frames. This currently means only Q043 and Q046. All other -// versions of QUIC (both Google QUIC and IETF) allow multi-packet CHLOs -// regardless of the value of this flag. -QUIC_PROTOCOL_FLAG(bool, quic_enforce_single_packet_chlo, true, - "If true, enforce that sent QUIC CHLOs fit in one packet. " - "Only applies to Q043 and Q046.") - -// Currently, this number is quite conservative. At a hypothetical 1000 qps, -// this means that the longest time-wait list we should see is: -// 200 seconds * 1000 qps = 200000. -// Of course, there are usually many queries per QUIC connection, so we allow a -// factor of 3 leeway. -QUIC_PROTOCOL_FLAG(int64_t, quic_time_wait_list_max_connections, 600000, - "Maximum number of connections on the time-wait list. " - "A negative value implies no configured limit.") - -QUIC_PROTOCOL_FLAG(int64_t, quic_time_wait_list_seconds, 200, - "Time period for which a given connection_id should live in " - "the time-wait state.") - -// This number is relatively conservative. For example, there are at most 1K -// queued stateless resets, which consume 1K * 21B = 21KB. -QUIC_PROTOCOL_FLAG( - uint64_t, quic_time_wait_list_max_pending_packets, 1024, - "Upper limit of pending packets in time wait list when writer is blocked.") - -// Stop sending a reset if the recorded number of addresses that server has -// recently sent stateless reset to exceeds this limit. -QUIC_PROTOCOL_FLAG(uint64_t, quic_max_recent_stateless_reset_addresses, 1024, - "Max number of recorded recent reset addresses.") - -// After this timeout, recent reset addresses will be cleared. -// FLAGS_quic_max_recent_stateless_reset_addresses * (1000ms / -// FLAGS_quic_recent_stateless_reset_addresses_lifetime_ms) is roughly the max -// reset per second. For example, 1024 * (1000ms / 1000ms) = 1K reset per -// second. -QUIC_PROTOCOL_FLAG( - uint64_t, quic_recent_stateless_reset_addresses_lifetime_ms, 1000, - "Max time that a client address lives in recent reset addresses set.") - -QUIC_PROTOCOL_FLAG(double, quic_bbr_cwnd_gain, 2.0f, - "Congestion window gain for QUIC BBR during PROBE_BW phase.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_buffered_data_threshold, 8 * 1024, - "If buffered data in QUIC stream is less than this " - "threshold, buffers all provided data or asks upper layer for more data") - -QUIC_PROTOCOL_FLAG( - uint64_t, quic_send_buffer_max_data_slice_size, 4 * 1024, - "Max size of data slice in bytes for QUIC stream send buffer.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_lumpy_pacing_size, 2, - "Number of packets that the pacing sender allows in bursts during " - "pacing. This flag is ignored if a flow's estimated bandwidth is " - "lower than 1200 kbps.") - -QUIC_PROTOCOL_FLAG( - double, quic_lumpy_pacing_cwnd_fraction, 0.25f, - "Congestion window fraction that the pacing sender allows in bursts " - "during pacing.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_lumpy_pacing_min_bandwidth_kbps, 1200, - "The minimum estimated client bandwidth below which the pacing sender will " - "not allow bursts.") - -QUIC_PROTOCOL_FLAG(int32_t, quic_max_pace_time_into_future_ms, 10, - "Max time that QUIC can pace packets into the future in ms.") - -QUIC_PROTOCOL_FLAG( - double, quic_pace_time_into_future_srtt_fraction, - 0.125f, // One-eighth smoothed RTT - "Smoothed RTT fraction that a connection can pace packets into the future.") - -QUIC_PROTOCOL_FLAG(bool, quic_export_write_path_stats_at_server, false, - "If true, export detailed write path statistics at server.") - -QUIC_PROTOCOL_FLAG(bool, quic_disable_version_negotiation_grease_randomness, - false, - "If true, use predictable version negotiation versions.") - -QUIC_PROTOCOL_FLAG(bool, quic_enable_http3_grease_randomness, true, - "If true, use random greased settings and frames.") - -QUIC_PROTOCOL_FLAG(int64_t, quic_max_tracked_packet_count, 10000, - "Maximum number of tracked packets.") - -QUIC_PROTOCOL_FLAG( - bool, quic_client_convert_http_header_name_to_lowercase, true, - "If true, HTTP request header names sent from QuicSpdyClientBase(and " - "descendents) will be automatically converted to lower case.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_probe_bw_base_duration_ms, 2000, - "The default minimum duration for BBRv2-native probes, in milliseconds.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_probe_bw_max_rand_duration_ms, 1000, - "The default upper bound of the random amount of BBRv2-native " - "probes, in milliseconds.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_probe_rtt_period_ms, 10000, - "The default period for entering PROBE_RTT, in milliseconds.") - -QUIC_PROTOCOL_FLAG( - double, quic_bbr2_default_loss_threshold, 0.02, - "The default loss threshold for QUIC BBRv2, should be a value " - "between 0 and 1.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_startup_full_loss_count, 8, - "The default minimum number of loss marking events to exit STARTUP.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_probe_bw_full_loss_count, 2, - "The default minimum number of loss marking events to exit PROBE_UP phase.") - -QUIC_PROTOCOL_FLAG( - double, quic_bbr2_default_inflight_hi_headroom, 0.15, - "The default fraction of unutilized headroom to try to leave in path " - "upon high loss.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_bbr2_default_initial_ack_height_filter_window, 10, - "The default initial value of the max ack height filter's window length.") - -QUIC_PROTOCOL_FLAG( - double, quic_ack_aggregation_bandwidth_threshold, 1.0, - "If the bandwidth during ack aggregation is smaller than (estimated " - "bandwidth * this flag), consider the current aggregation completed " - "and starts a new one.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_anti_amplification_factor, 3, - "Anti-amplification factor. Before address validation, server will " - "send no more than factor times bytes received.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_max_buffered_crypto_bytes, - 16 * 1024, // 16 KB - "The maximum amount of CRYPTO frame data that can be buffered.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_max_aggressive_retransmittable_on_wire_ping_count, 5, - "Maximum number of consecutive pings that can be sent with the " - "aggressive initial retransmittable on the wire timeout if there is " - "no new stream data received. After this limit, the timeout will be " - "doubled each ping until it exceeds the default ping timeout.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_max_retransmittable_on_wire_ping_count, 1000, - "Maximum number of pings that can be sent with the retransmittable " - "on the wire timeout, over the lifetime of a connection. After this " - "limit, the timeout will be the default ping timeout.") - -QUIC_PROTOCOL_FLAG(int32_t, quic_max_congestion_window, 2000, - "The maximum congestion window in packets.") - -QUIC_PROTOCOL_FLAG( - int32_t, quic_max_streams_window_divisor, 2, - "The divisor that controls how often MAX_STREAMS frame is sent.") - -QUIC_PROTOCOL_FLAG( - uint64_t, quic_key_update_confidentiality_limit, 0, - "If non-zero and key update is allowed, the maximum number of " - "packets sent for each key phase before initiating a key update.") - -QUIC_PROTOCOL_FLAG(bool, quic_disable_client_tls_zero_rtt, false, - "If true, QUIC client with TLS will not try 0-RTT.") - -QUIC_PROTOCOL_FLAG(bool, quic_disable_server_tls_resumption, false, - "If true, QUIC server will disable TLS resumption by not " - "issuing or processing session tickets.") - -QUIC_PROTOCOL_FLAG(bool, quic_defer_send_in_response, true, - "If true, QUIC servers will defer sending in response to " - "incoming packets by default.") - -QUIC_PROTOCOL_FLAG( - bool, quic_header_size_limit_includes_overhead, true, - "If true, QUIC QPACK decoder includes 32-bytes overheader per entry while " - "comparing request/response header size against its upper limit.") - -QUIC_PROTOCOL_FLAG( - bool, quic_reject_retry_token_in_initial_packet, false, - "If true, always reject retry_token received in INITIAL packets") - -QUIC_PROTOCOL_FLAG(bool, quic_use_lower_server_response_mtu_for_test, false, - "If true, cap server response packet size at 1250.") - -QUIC_PROTOCOL_FLAG(bool, quic_enforce_strict_amplification_factor, false, - "If true, enforce strict amplification factor") - -QUIC_PROTOCOL_FLAG(bool, quic_bounded_crypto_send_buffer, false, - "If true, close the connection if a crypto send buffer " - "exceeds its size limit.") - -QUIC_PROTOCOL_FLAG(bool, quic_interval_set_enable_add_optimization, true, - "If true, enable an optimization in QuicIntervalSet") - -QUIC_PROTOCOL_FLAG(bool, quic_server_disable_qpack_dynamic_table, false, - "If true, disables use of the QPACK dynamic table in " - "servers, both for decoding context (requests) and for " - "encoding context (responses).") - -QUIC_PROTOCOL_FLAG( - bool, quic_enable_chaos_protection, true, - "If true, use chaos protection to randomize client initials.") - -#endif diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc index 46cc259c4c..6cef3e42b0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_received_packet_manager.cc @@ -124,8 +124,7 @@ void QuicReceivedPacketManager::RecordPacketReceived( } } - if (GetQuicRestartFlag(quic_receive_ecn3) && ecn != ECN_NOT_ECT) { - QUIC_RESTART_FLAG_COUNT_N(quic_receive_ecn3, 1, 2); + if (ecn != ECN_NOT_ECT) { if (!ack_frame_.ecn_counters.has_value()) { ack_frame_.ecn_counters = QuicEcnCounts(); } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc index 6e655c5b93..359841a16a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_session.cc @@ -1384,7 +1384,7 @@ void QuicSession::OnConfigNegotiated() { if (perspective_ == Perspective::IS_SERVER && version().HasIetfQuicFrames() && connection_->effective_peer_address().IsInitialized()) { - if (config_.HasClientSentConnectionOption(kSPAD, perspective_)) { + if (config_.SupportsServerPreferredAddress(perspective_)) { quiche::IpAddressFamily address_family = connection_->effective_peer_address() .Normalized() diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc index 1db3cd3100..4de14d7ddd 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.cc @@ -763,7 +763,8 @@ QuicConsumedData QuicStream::WriteMemSlice(quiche::QuicheMemSlice span, } QuicConsumedData QuicStream::WriteMemSlices( - absl::Span span, bool fin) { + absl::Span span, bool fin, + bool buffer_unconditionally) { QuicConsumedData consumed_data(0, false); if (span.empty() && !fin) { QUIC_BUG(quic_bug_10586_6) << "span.empty() && !fin"; @@ -786,7 +787,7 @@ QuicConsumedData QuicStream::WriteMemSlices( } bool had_buffered_data = HasBufferedData(); - if (CanWriteNewData() || span.empty()) { + if (CanWriteNewData() || span.empty() || buffer_unconditionally) { consumed_data.fin_consumed = fin; if (!span.empty()) { // Buffer all data if buffered data size is below limit. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h index b7ea9e7de4..c846fe0275 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_stream.h @@ -353,9 +353,10 @@ class QUICHE_EXPORT QuicStream : public QuicStreamSequencer::StreamInterface { // Commits data into the stream write buffer, and potentially sends it over // the wire. This method has all-or-nothing semantics: if the write buffer is // not full, all of the memslices in |span| are moved into it; otherwise, - // nothing happens. + // nothing happens. If `buffer_unconditionally` is set to true, behaves + // similar to `WriteOrBufferData()` in terms of buffering. QuicConsumedData WriteMemSlices(absl::Span span, - bool fin); + bool fin, bool buffer_uncondtionally = false); QuicConsumedData WriteMemSlice(quiche::QuicheMemSlice span, bool fin); // Returns true if any stream data is lost (including fin) and needs to be diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor.cc index 7906536195..2b049ca1cb 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_trace_visitor.cc @@ -94,6 +94,7 @@ void QuicTraceVisitor::OnPacketSent( case MESSAGE_FRAME: case CRYPTO_FRAME: case NEW_TOKEN_FRAME: + case RESET_STREAM_AT_FRAME: break; // Ignore gQUIC-specific frames. @@ -226,6 +227,7 @@ void QuicTraceVisitor::PopulateFrameInfo(const QuicFrame& frame, case CRYPTO_FRAME: case NEW_TOKEN_FRAME: case ACK_FREQUENCY_FRAME: + case RESET_STREAM_AT_FRAME: break; case NUM_FRAME_TYPES: diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc index b7b2b2671e..2555384f89 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.cc @@ -157,6 +157,7 @@ std::string QuicFrameTypeToString(QuicFrameType t) { RETURN_STRING_LITERAL(NEW_TOKEN_FRAME) RETURN_STRING_LITERAL(RETIRE_CONNECTION_ID_FRAME) RETURN_STRING_LITERAL(ACK_FREQUENCY_FRAME) + RETURN_STRING_LITERAL(RESET_STREAM_AT_FRAME) RETURN_STRING_LITERAL(NUM_FRAME_TYPES) } return absl::StrCat("Unknown(", static_cast(t), ")"); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h index b626531ee8..96e075c939 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_types.h @@ -275,6 +275,7 @@ enum QuicFrameType : uint8_t { NEW_TOKEN_FRAME, RETIRE_CONNECTION_ID_FRAME, ACK_FREQUENCY_FRAME, + RESET_STREAM_AT_FRAME, NUM_FRAME_TYPES }; @@ -347,6 +348,9 @@ enum QuicIetfFrameType : uint64_t { // packet receive timestamps. // TODO(ianswett): Determine a proper value to replace this temporary value. IETF_ACK_RECEIVE_TIMESTAMPS = 0x22, + + // https://datatracker.ietf.org/doc/html/draft-ietf-quic-reliable-stream-reset + IETF_RESET_STREAM_AT = 0x24, }; QUICHE_EXPORT std::ostream& operator<<(std::ostream& os, const QuicIetfFrameType& c); @@ -357,7 +361,7 @@ QUICHE_EXPORT std::string QuicIetfFrameTypeString(QuicIetfFrameType t); #define IETF_STREAM_FRAME_TYPE_MASK 0xfffffffffffffff8 #define IETF_STREAM_FRAME_FLAG_MASK 0x07 #define IS_IETF_STREAM_FRAME(_stype_) \ - (((_stype_)&IETF_STREAM_FRAME_TYPE_MASK) == IETF_STREAM) + (((_stype_) & IETF_STREAM_FRAME_TYPE_MASK) == IETF_STREAM) // These are the values encoded in the low-order 3 bits of the // IETF_STREAMx frame type. @@ -447,7 +451,8 @@ enum CongestionControlType { kBBR, kPCC, kGoogCC, - kBBRv2, + kBBRv2, // TODO(rch): This is effectively BBRv3. We should finish the + // implementation and rename this enum. }; QUICHE_EXPORT std::string CongestionControlTypeToString( diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc index a89cf80421..adebba4409 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/quic_unacked_packet_map.cc @@ -52,6 +52,7 @@ enum QuicFrameTypeBitfield : uint32_t { kNewTokenFrameBitfield = 1 << 20, kRetireConnectionIdFrameBitfield = 1 << 21, kAckFrequencyFrameBitfield = 1 << 22, + kResetStreamAtFrameBitfield = 1 << 23, }; QuicFrameTypeBitfield GetFrameTypeBitfield(QuicFrameType type) { @@ -102,6 +103,8 @@ QuicFrameTypeBitfield GetFrameTypeBitfield(QuicFrameType type) { return kRetireConnectionIdFrameBitfield; case ACK_FREQUENCY_FRAME: return kAckFrequencyFrameBitfield; + case RESET_STREAM_AT_FRAME: + return kResetStreamAtFrameBitfield; case NUM_FRAME_TYPES: QUIC_BUG(quic_bug_10518_1) << "Unexpected frame type"; return kInvalidFrameBitfield; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h index c8d781076b..2aaa0eb816 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_chlo_extractor.h @@ -13,6 +13,7 @@ #include "absl/types/span.h" #include "openssl/ssl.h" #include "quiche/quic/core/frames/quic_ack_frequency_frame.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_framer.h" #include "quiche/quic/core/quic_packets.h" #include "quiche/quic/core/quic_stream_sequencer.h" @@ -177,6 +178,9 @@ class QUICHE_EXPORT TlsChloExtractor bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& /*frame*/) override { return true; } + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& /*frame*/) override { + return true; + } void OnPacketComplete() override {} bool IsValidStatelessResetToken( const StatelessResetToken& /*token*/) const override { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc index d819703072..9ab0c834f9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.cc @@ -4,25 +4,55 @@ #include "quiche/quic/core/tls_server_handshaker.h" +#include +#include +#include #include +#include #include +#include +#include -#include "absl/base/macros.h" +#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" -#include "openssl/pool.h" +#include "absl/types/span.h" +#include "absl/types/variant.h" +#include "openssl/base.h" +#include "openssl/bytestring.h" #include "openssl/ssl.h" +#include "openssl/tls1.h" +#include "quiche/quic/core/crypto/crypto_handshake.h" +#include "quiche/quic/core/crypto/crypto_message_parser.h" +#include "quiche/quic/core/crypto/crypto_utils.h" +#include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/proof_verifier.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/crypto/quic_decrypter.h" +#include "quiche/quic/core/crypto/quic_encrypter.h" #include "quiche/quic/core/crypto/transport_parameters.h" #include "quiche/quic/core/http/http_encoder.h" #include "quiche/quic/core/http/http_frames.h" +#include "quiche/quic/core/quic_config.h" +#include "quiche/quic/core/quic_connection.h" +#include "quiche/quic/core/quic_connection_context.h" +#include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_connection_stats.h" +#include "quiche/quic/core/quic_crypto_server_stream_base.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_session.h" #include "quiche/quic/core/quic_time.h" +#include "quiche/quic/core/quic_time_accumulator.h" #include "quiche/quic/core/quic_types.h" +#include "quiche/quic/core/quic_versions.h" +#include "quiche/quic/core/tls_handshaker.h" +#include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/quic/platform/api/quic_flag_utils.h" #include "quiche/quic/platform/api/quic_flags.h" #include "quiche/quic/platform/api/quic_hostname_utils.h" #include "quiche/quic/platform/api/quic_logging.h" #include "quiche/quic/platform/api/quic_server_stats.h" +#include "quiche/quic/platform/api/quic_socket_address.h" #define RECORD_LATENCY_IN_US(stat_name, latency, comment) \ do { \ @@ -81,10 +111,10 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate( &cert_matched_sni); handshaker_->OnSelectCertificateDone( - /*ok=*/true, /*is_sync=*/true, chain.get(), - /*handshake_hints=*/absl::string_view(), - /*ticket_encryption_key=*/absl::string_view(), cert_matched_sni, - QuicDelayedSSLConfig()); + /*ok=*/true, /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + QuicDelayedSSLConfig()}, + /*ticket_encryption_key=*/absl::string_view(), cert_matched_sni); if (!handshaker_->select_cert_status().has_value()) { QUIC_BUG(quic_bug_12423_1) << "select_cert_status() has no value after a synchronous select cert"; @@ -1007,13 +1037,10 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback( } void TlsServerHandshaker::OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, absl::string_view ticket_encryption_key, - bool cert_matched_sni, QuicDelayedSSLConfig delayed_ssl_config) { + bool ok, bool is_sync, SSLConfig ssl_config, + absl::string_view ticket_encryption_key, bool cert_matched_sni) { QUIC_DVLOG(1) << "OnSelectCertificateDone. ok:" << ok - << ", is_sync:" << is_sync - << ", len(handshake_hints):" << handshake_hints.size() - << ", len(ticket_encryption_key):" + << ", is_sync:" << is_sync << ", len(ticket_encryption_key):" << ticket_encryption_key.size(); std::optional context_switcher; if (!is_sync) { @@ -1022,14 +1049,17 @@ void TlsServerHandshaker::OnSelectCertificateDone( QUIC_TRACESTRING(absl::StrCat( "TLS select certificate done: ok:", ok, - ", certs_found:", (chain != nullptr && !chain->certs.empty()), - ", len(handshake_hints):", handshake_hints.size(), ", len(ticket_encryption_key):", ticket_encryption_key.size())); ticket_encryption_key_ = std::string(ticket_encryption_key); select_cert_status_ = QUIC_FAILURE; cert_matched_sni_ = cert_matched_sni; + // Extract the delayed SSL config from either LocalSSLConfig or + // HintsSSLConfig. + const QuicDelayedSSLConfig& delayed_ssl_config = absl::visit( + [](const auto& config) { return config.delayed_ssl_config; }, ssl_config); + if (delayed_ssl_config.quic_transport_parameters.has_value()) { // In case of any error the SSL object is still valid. Handshaker may need // to call ComputeSignature but otherwise can proceed. @@ -1053,25 +1083,33 @@ void TlsServerHandshaker::OnSelectCertificateDone( } if (ok) { - if (chain && !chain->certs.empty()) { - tls_connection_.SetCertChain(chain->ToCryptoBuffers().value); - if (!handshake_hints.empty() && - !SSL_set_handshake_hints( - ssl(), reinterpret_cast(handshake_hints.data()), - handshake_hints.size())) { - // If |SSL_set_handshake_hints| fails, the ssl() object will remain - // intact, it is as if we didn't call it. The handshaker will - // continue to compute signature/decrypt ticket as normal. - QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed); - QUIC_DVLOG(1) << "SSL_set_handshake_hints failed"; + if (auto* local_config = absl::get_if(&ssl_config); + local_config != nullptr) { + if (local_config->chain && !local_config->chain->certs.empty()) { + tls_connection_.SetCertChain( + local_config->chain->ToCryptoBuffers().value); + select_cert_status_ = QUIC_SUCCESS; + } else { + QUIC_DLOG(ERROR) << "No certs provided for host '" + << crypto_negotiated_params_->sni + << "', server_address:" + << session()->connection()->self_address() + << ", client_address:" + << session()->connection()->peer_address(); + } + } else if (auto* hints_config = absl::get_if(&ssl_config); + hints_config != nullptr) { + if (hints_config->configure_ssl) { + if (const absl::Status status = tls_connection_.ConfigureSSL( + std::move(hints_config->configure_ssl)); + !status.ok()) { + QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed); + QUIC_DVLOG(1) << "SSL_set_handshake_hints failed: " << status; + } + select_cert_status_ = QUIC_SUCCESS; } - select_cert_status_ = QUIC_SUCCESS; } else { - QUIC_DLOG(ERROR) << "No certs provided for host '" - << crypto_negotiated_params_->sni << "', server_address:" - << session()->connection()->self_address() - << ", client_address:" - << session()->connection()->peer_address(); + QUIC_DLOG(FATAL) << "Neither branch hit"; } } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h index 5f571edc70..2e0351ea34 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/core/tls_server_handshaker.h @@ -5,23 +5,40 @@ #ifndef QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ #define QUICHE_QUIC_CORE_TLS_SERVER_HANDSHAKER_H_ +#include +#include +#include +#include #include +#include +#include #include "absl/strings/string_view.h" -#include "openssl/pool.h" +#include "absl/types/span.h" +#include "openssl/base.h" #include "openssl/ssl.h" +#include "quiche/quic/core/crypto/crypto_handshake.h" +#include "quiche/quic/core/crypto/crypto_message_parser.h" +#include "quiche/quic/core/crypto/proof_source.h" +#include "quiche/quic/core/crypto/proof_verifier.h" #include "quiche/quic/core/crypto/quic_crypto_server_config.h" +#include "quiche/quic/core/crypto/quic_decrypter.h" +#include "quiche/quic/core/crypto/quic_encrypter.h" +#include "quiche/quic/core/crypto/tls_connection.h" #include "quiche/quic/core/crypto/tls_server_connection.h" -#include "quiche/quic/core/proto/cached_network_parameters_proto.h" +#include "quiche/quic/core/crypto/transport_parameters.h" +#include "quiche/quic/core/quic_config.h" +#include "quiche/quic/core/quic_connection_context.h" #include "quiche/quic/core/quic_connection_id.h" +#include "quiche/quic/core/quic_connection_stats.h" #include "quiche/quic/core/quic_crypto_server_stream_base.h" #include "quiche/quic/core/quic_crypto_stream.h" +#include "quiche/quic/core/quic_error_codes.h" +#include "quiche/quic/core/quic_time.h" #include "quiche/quic/core/quic_time_accumulator.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/core/tls_handshaker.h" -#include "quiche/quic/platform/api/quic_export.h" -#include "quiche/quic/platform/api/quic_flag_utils.h" -#include "quiche/quic/platform/api/quic_flags.h" +#include "quiche/quic/platform/api/quic_socket_address.h" namespace quic { @@ -178,11 +195,9 @@ class QUICHE_EXPORT TlsServerHandshaker : public TlsHandshaker, bool HasValidSignature(size_t max_signature_size) const; // ProofSourceHandleCallback implementation: - void OnSelectCertificateDone( - bool ok, bool is_sync, const ProofSource::Chain* chain, - absl::string_view handshake_hints, - absl::string_view ticket_encryption_key, bool cert_matched_sni, - QuicDelayedSSLConfig delayed_ssl_config) override; + void OnSelectCertificateDone(bool ok, bool is_sync, SSLConfig ssl_config, + absl::string_view ticket_encryption_key, + bool cert_matched_sni) override; void OnComputeSignatureDone( bool ok, bool is_sync, std::string signature, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/load_balancer/load_balancer_config.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/load_balancer/load_balancer_config.cc index b4b989eaf6..70c2590278 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/load_balancer/load_balancer_config.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/load_balancer/load_balancer_config.cc @@ -89,18 +89,22 @@ std::optional LoadBalancerConfig::CreateUnencrypted( : std::optional(); } +// Note that |ciphertext| does not include the first byte of the connection ID. bool LoadBalancerConfig::FourPassDecrypt( absl::Span ciphertext, LoadBalancerServerId& server_id) const { - QUIC_BUG_IF(quic_bug_599862571_02, ciphertext.size() < plaintext_len()) - << "Called FourPassDecrypt with a short Connection ID"; + if (ciphertext.size() < plaintext_len()) { + QUIC_BUG(quic_bug_599862571_02) + << "Called FourPassDecrypt with a short Connection ID"; + return false; + } if (!key_.has_value()) { return false; } // Do 3 or 4 passes. Only 3 are necessary if the server_id is short enough // to fit in the first half of the connection ID (the decoder doesn't need // to extract the nonce). - uint8_t left[kLoadBalancerBlockSize]; + uint8_t* left = server_id.mutable_data(); uint8_t right[kLoadBalancerBlockSize]; uint8_t half_len; // half the length of the plaintext, rounded up bool is_length_odd = @@ -114,23 +118,25 @@ bool LoadBalancerConfig::FourPassDecrypt( // Consolidate left and right into a server ID with minimum copying. if (server_id_len_ < half_len || (server_id_len_ == half_len && !is_length_odd)) { - // There is no half-byte to handle - memcpy(server_id.mutable_data(), &left[2], server_id_len_); + // There is no half-byte to handle. Server ID is already written in to + // server_id. return true; } if (is_length_odd) { - right[2] |= left[half_len-- + 1]; // Combine the halves of the odd byte. + right[0] |= *(left + --half_len); // Combine the halves of the odd byte. } - memcpy(server_id.mutable_data(), &left[2], half_len); - memcpy(server_id.mutable_data() + half_len, &right[2], - server_id_len_ - half_len); + memcpy(server_id.mutable_data() + half_len, right, server_id_len_ - half_len); return true; } +// Note that |plaintext| includes the first byte of the connection ID. QuicConnectionId LoadBalancerConfig::FourPassEncrypt( absl::Span plaintext) const { - QUIC_BUG_IF(quic_bug_599862571_03, plaintext.size() < total_len()) - << "Called FourPassEncrypt with a short Connection ID"; + if (plaintext.size() < total_len()) { + QUIC_BUG(quic_bug_599862571_03) + << "Called FourPassEncrypt with a short Connection ID"; + return QuicConnectionId(); + } if (!key_.has_value()) { return QuicConnectionId(); } @@ -145,14 +151,10 @@ QuicConnectionId LoadBalancerConfig::FourPassEncrypt( // Consolidate left and right into a server ID with minimum copying. if (is_length_odd) { // Combine the halves of the odd byte. - left[half_len + 1] |= right[2]; - } - memcpy(plaintext.data() + 1, &left[2], half_len); - if (is_length_odd) { - memcpy(plaintext.data() + 1 + half_len, &right[3], half_len - 1); - } else { - memcpy(plaintext.data() + 1 + half_len, &right[2], half_len); + right[0] |= left[--half_len]; } + memcpy(plaintext.data() + 1, left, half_len); + memcpy(plaintext.data() + half_len + 1, right, plaintext_len() - half_len); return QuicConnectionId(reinterpret_cast(plaintext.data()), total_len()); } @@ -189,6 +191,7 @@ LoadBalancerConfig::LoadBalancerConfig(const uint8_t config_id, ? BuildKey(key, /* encrypt = */ false) : std::optional()) {} +// Note that |input| does not include the first byte of the connection ID. bool LoadBalancerConfig::InitializeFourPass(const uint8_t* input, uint8_t* left, uint8_t* right, uint8_t* half_len) const { @@ -204,17 +207,17 @@ bool LoadBalancerConfig::InitializeFourPass(const uint8_t* input, uint8_t* left, memset(right, 0, kLoadBalancerBlockSize); // The first byte is the plaintext/ciphertext length, the second byte will be // the index of the pass. Half the plaintext or ciphertext follows. - left[0] = plaintext_len(); - right[0] = plaintext_len(); - // Leave left_[1], right_[1] as zero. It will be set for each pass. - memcpy(&left[2], input, *half_len); + left[kLoadBalancerBlockSize - 2] = plaintext_len(); + right[kLoadBalancerBlockSize - 2] = plaintext_len(); + // Leave left_[15]], right_[15] as zero. It will be set for each pass. + memcpy(left, input, *half_len); // If is_length_odd, then both left and right will have part of the middle // byte. Then that middle byte will be split in half via the bitmask in the // next step. - memcpy(&right[2], input + (plaintext_len() / 2), *half_len); + memcpy(right, input + (plaintext_len() / 2), *half_len); if (is_length_odd) { - left[*half_len + 1] &= 0xf0; - right[2] &= 0x0f; + left[*half_len - 1] &= 0xf0; + right[0] &= 0x0f; } return is_length_odd; } @@ -224,26 +227,26 @@ void LoadBalancerConfig::EncryptionPass(uint8_t index, uint8_t half_len, uint8_t* right) const { uint8_t ciphertext[kLoadBalancerBlockSize]; if (index % 2 == 0) { // Go right to left. - right[1] = index; + right[kLoadBalancerBlockSize - 1] = index; AES_encrypt(right, ciphertext, &*key_); for (int i = 0; i < half_len; ++i) { // Skip over the first two bytes, which have the plaintext_len and the // index. The CID bits are in [2, half_len - 1]. - left[2 + i] ^= ciphertext[i]; + left[i] ^= ciphertext[i]; } if (is_length_odd) { - left[half_len + 1] &= 0xf0; + left[half_len - 1] &= 0xf0; } return; } // Go left to right. - left[1] = index; + left[kLoadBalancerBlockSize - 1] = index; AES_encrypt(left, ciphertext, &*key_); for (int i = 0; i < half_len; ++i) { - right[2 + i] ^= ciphertext[i]; + right[i] ^= ciphertext[i]; } if (is_length_odd) { - right[2] &= 0x0f; + right[0] &= 0x0f; } } diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc index 10a7c394d6..eefd002dc5 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_bin.cc @@ -439,7 +439,7 @@ int RunMasqueClient(int argc, char* argv[]) { quiche::GetQuicheCommandLineFlag(FLAGS_dns_on_client); for (size_t i = 1; i < urls.size(); ++i) { - if (urls[i].starts_with("/")) { + if (absl::StartsWith(urls[i], "/")) { QuicSpdyClientStream* stream = masque_client->masque_client_session()->SendGetRequest(urls[i]); while (stream->time_to_response_complete().IsInfinite()) { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc index 842e454a6c..7e5dfddbce 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/masque/masque_client_session.cc @@ -169,7 +169,6 @@ MasqueClientSession::GetOrCreateConnectUdpClientState( headers[":scheme"] = scheme; headers[":authority"] = authority; headers[":path"] = canonicalized_path; - headers["connect-udp-version"] = "12"; AddAdditionalHeaders(headers, url); QUIC_DVLOG(1) << "Sending request headers: " << headers.DebugString(); size_t bytes_sent = diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc index a0b5f40a2f..61caf1ecb9 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.cc @@ -11,8 +11,8 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_data_writer.h" #include "quiche/quic/core/quic_time.h" -#include "quiche/quic/core/quic_types.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/platform/api/quic_bug_tracker.h" #include "quiche/common/quiche_buffer_allocator.h" namespace moqt { @@ -91,7 +91,7 @@ inline bool WriteLocation(quic::QuicDataWriter& writer, } return writer.WriteVarInt62(loc->absolute_value); } - if (loc->relative_value < 0) { + if (loc->relative_value <= 0) { if (!writer.WriteVarInt62(static_cast( MoqtSubscribeLocationMode::kRelativePrevious))) { return false; @@ -103,39 +103,73 @@ inline bool WriteLocation(quic::QuicDataWriter& writer, static_cast(MoqtSubscribeLocationMode::kRelativeNext))) { return false; } - return writer.WriteVarInt62(static_cast(loc->relative_value)); + return writer.WriteVarInt62(static_cast(loc->relative_value - 1)); } } // namespace quiche::QuicheBuffer MoqtFramer::SerializeObject( - const MoqtObject& message, const absl::string_view payload) { + const MoqtObject& message, const absl::string_view payload, + bool is_first_in_stream) { if (message.payload_length.has_value() && *message.payload_length < payload.length()) { - QUICHE_DLOG(INFO) << "payload_size is too small for payload"; + QUIC_BUG(quic_bug_serialize_object_input_01) + << "payload_size is too small for payload"; return quiche::QuicheBuffer(); } - uint64_t message_type = - static_cast(message.payload_length.has_value() - ? MoqtMessageType::kObjectWithPayloadLength - : MoqtMessageType::kObjectWithoutPayloadLength); - size_t buffer_size = - NeededVarIntLen(message_type) + NeededVarIntLen(message.track_id) + - NeededVarIntLen(message.group_sequence) + - NeededVarIntLen(message.object_sequence) + - NeededVarIntLen(message.object_send_order) + payload.length(); - if (message.payload_length.has_value()) { - buffer_size += NeededVarIntLen(*message.payload_length); + if (!is_first_in_stream && + (message.forwarding_preference == MoqtForwardingPreference::kObject || + message.forwarding_preference == MoqtForwardingPreference::kDatagram)) { + QUIC_BUG(quic_bug_serialize_object_input_02) + << "Object or Datagram forwarding_preference must be first in stream"; + return quiche::QuicheBuffer(); } + // Figure out the total message size based on message type and payload. + size_t buffer_size = NeededVarIntLen(message.object_id) + payload.length(); + uint64_t message_type = static_cast( + GetMessageTypeForForwardingPreference(message.forwarding_preference)); + if (is_first_in_stream) { + buffer_size += NeededVarIntLen(message_type) + + NeededVarIntLen(message.subscribe_id) + + NeededVarIntLen(message.track_alias) + + NeededVarIntLen(message.group_id) + + NeededVarIntLen(message.object_send_order); + } else if (message.forwarding_preference == + MoqtForwardingPreference::kTrack) { + buffer_size += NeededVarIntLen(message.group_id); + } + uint64_t reported_payload_length = message.payload_length.has_value() + ? message.payload_length.value() + : payload.length(); + if (message.forwarding_preference == MoqtForwardingPreference::kTrack || + message.forwarding_preference == MoqtForwardingPreference::kGroup) { + buffer_size += NeededVarIntLen(reported_payload_length); + } + // Write to buffer. quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); - writer.WriteVarInt62(message_type); - writer.WriteVarInt62(message.track_id); - writer.WriteVarInt62(message.group_sequence); - writer.WriteVarInt62(message.object_sequence); - writer.WriteVarInt62(message.object_send_order); - if (message.payload_length.has_value()) { - writer.WriteVarInt62(*message.payload_length); + if (is_first_in_stream) { + writer.WriteVarInt62(message_type); + writer.WriteVarInt62(message.subscribe_id); + writer.WriteVarInt62(message.track_alias); + if (message.forwarding_preference != MoqtForwardingPreference::kTrack) { + writer.WriteVarInt62(message.group_id); + if (message.forwarding_preference != MoqtForwardingPreference::kGroup) { + writer.WriteVarInt62(message.object_id); + } + } + writer.WriteVarInt62(message.object_send_order); + } + switch (message.forwarding_preference) { + case MoqtForwardingPreference::kTrack: + writer.WriteVarInt62(message.group_id); + [[fallthrough]]; + case MoqtForwardingPreference::kGroup: + writer.WriteVarInt62(message.object_id); + writer.WriteVarInt62(reported_payload_length); + break; + default: + break; } writer.WriteStringPiece(payload); return buffer; @@ -216,8 +250,8 @@ quiche::QuicheBuffer MoqtFramer::SerializeServerSetup( return buffer; } -quiche::QuicheBuffer MoqtFramer::SerializeSubscribeRequest( - const MoqtSubscribeRequest& message) { +quiche::QuicheBuffer MoqtFramer::SerializeSubscribe( + const MoqtSubscribe& message) { if (!message.start_group.has_value() || !message.start_object.has_value()) { QUIC_LOG(INFO) << "start_group or start_object is missing"; return quiche::QuicheBuffer(); @@ -227,7 +261,9 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeRequest( << "non-None"; return quiche::QuicheBuffer(); } - size_t buffer_size = NeededVarIntLen(MoqtMessageType::kSubscribeRequest) + + size_t buffer_size = NeededVarIntLen(MoqtMessageType::kSubscribe) + + NeededVarIntLen(message.subscribe_id) + + NeededVarIntLen(message.track_alias) + LengthPrefixedStringLength(message.track_namespace) + LengthPrefixedStringLength(message.track_name) + LocationLength(message.start_group) + @@ -244,8 +280,9 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeRequest( buffer_size += NeededVarIntLen(num_params); quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); - writer.WriteVarInt62( - static_cast(MoqtMessageType::kSubscribeRequest)); + writer.WriteVarInt62(static_cast(MoqtMessageType::kSubscribe)); + writer.WriteVarInt62(static_cast(message.subscribe_id)); + writer.WriteVarInt62(static_cast(message.track_alias)); writer.WriteStringPieceVarInt62(message.track_namespace); writer.WriteStringPieceVarInt62(message.track_name); WriteLocation(writer, message.start_group); @@ -267,16 +304,12 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeOk( const MoqtSubscribeOk& message) { size_t buffer_size = NeededVarIntLen(static_cast(MoqtMessageType::kSubscribeOk)) + - LengthPrefixedStringLength(message.track_namespace) + - LengthPrefixedStringLength(message.track_name) + - NeededVarIntLen(message.track_id) + + NeededVarIntLen(message.subscribe_id) + NeededVarIntLen(message.expires.ToMilliseconds()); quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); writer.WriteVarInt62(static_cast(MoqtMessageType::kSubscribeOk)); - writer.WriteStringPieceVarInt62(message.track_namespace); - writer.WriteStringPieceVarInt62(message.track_name); - writer.WriteVarInt62(message.track_id); + writer.WriteVarInt62(message.subscribe_id); writer.WriteVarInt62(message.expires.ToMilliseconds()); QUICHE_DCHECK(writer.remaining() == 0); return buffer; @@ -286,17 +319,17 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeError( const MoqtSubscribeError& message) { size_t buffer_size = NeededVarIntLen(static_cast(MoqtMessageType::kSubscribeError)) + - LengthPrefixedStringLength(message.track_namespace) + - LengthPrefixedStringLength(message.track_name) + - NeededVarIntLen(message.error_code) + - LengthPrefixedStringLength(message.reason_phrase); + NeededVarIntLen(message.subscribe_id) + + NeededVarIntLen(static_cast(message.error_code)) + + LengthPrefixedStringLength(message.reason_phrase) + + NeededVarIntLen(message.track_alias); quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); writer.WriteVarInt62(static_cast(MoqtMessageType::kSubscribeError)); - writer.WriteStringPieceVarInt62(message.track_namespace); - writer.WriteStringPieceVarInt62(message.track_name); - writer.WriteVarInt62(message.error_code); + writer.WriteVarInt62(message.subscribe_id); + writer.WriteVarInt62(static_cast(message.error_code)); writer.WriteStringPieceVarInt62(message.reason_phrase); + writer.WriteVarInt62(message.track_alias); QUICHE_DCHECK(writer.remaining() == 0); return buffer; } @@ -305,13 +338,11 @@ quiche::QuicheBuffer MoqtFramer::SerializeUnsubscribe( const MoqtUnsubscribe& message) { size_t buffer_size = NeededVarIntLen(static_cast(MoqtMessageType::kUnsubscribe)) + - LengthPrefixedStringLength(message.track_namespace) + - LengthPrefixedStringLength(message.track_name); + NeededVarIntLen(message.subscribe_id); quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); writer.WriteVarInt62(static_cast(MoqtMessageType::kUnsubscribe)); - writer.WriteStringPieceVarInt62(message.track_namespace); - writer.WriteStringPieceVarInt62(message.track_name); + writer.WriteVarInt62(message.subscribe_id); QUICHE_DCHECK(writer.remaining() == 0); return buffer; } @@ -320,15 +351,13 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeFin( const MoqtSubscribeFin& message) { size_t buffer_size = NeededVarIntLen(static_cast(MoqtMessageType::kSubscribeFin)) + - LengthPrefixedStringLength(message.track_namespace) + - LengthPrefixedStringLength(message.track_name) + + NeededVarIntLen(message.subscribe_id) + NeededVarIntLen(message.final_group) + NeededVarIntLen(message.final_object); quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); writer.WriteVarInt62(static_cast(MoqtMessageType::kSubscribeFin)); - writer.WriteStringPieceVarInt62(message.track_namespace); - writer.WriteStringPieceVarInt62(message.track_name); + writer.WriteVarInt62(message.subscribe_id); writer.WriteVarInt62(message.final_group); writer.WriteVarInt62(message.final_object); QUICHE_DCHECK(writer.remaining() == 0); @@ -339,8 +368,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeRst( const MoqtSubscribeRst& message) { size_t buffer_size = NeededVarIntLen(static_cast(MoqtMessageType::kSubscribeRst)) + - LengthPrefixedStringLength(message.track_namespace) + - LengthPrefixedStringLength(message.track_name) + + NeededVarIntLen(message.subscribe_id) + NeededVarIntLen(message.error_code) + LengthPrefixedStringLength(message.reason_phrase) + NeededVarIntLen(message.final_group) + @@ -348,8 +376,7 @@ quiche::QuicheBuffer MoqtFramer::SerializeSubscribeRst( quiche::QuicheBuffer buffer(allocator_, buffer_size); quic::QuicDataWriter writer(buffer.size(), buffer.data()); writer.WriteVarInt62(static_cast(MoqtMessageType::kSubscribeRst)); - writer.WriteStringPieceVarInt62(message.track_namespace); - writer.WriteStringPieceVarInt62(message.track_name); + writer.WriteVarInt62(message.subscribe_id); writer.WriteVarInt62(message.error_code); writer.WriteStringPieceVarInt62(message.reason_phrase); writer.WriteVarInt62(message.final_group); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h index a5f741b5ed..080e76ee67 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_framer.h @@ -34,17 +34,21 @@ class QUICHE_EXPORT MoqtFramer { // SerializeObject also takes a payload. |payload_size| might simply be the // size of |payload|, or it could be larger if there is more data coming, or - // it could be nullopt if the final length is unknown. If |payload_size| is - // smaller than |payload|, returns an empty buffer. + // it could be nullopt if the final length is unknown. + // If |message.payload_size| is nullopt but the forwarding preference requires + // a payload length, will assume that payload.length() is the correct value. + // If |message.payload_size| is smaller than |payload|, or + // |message.forwarding preference| is not consistent with + // |is_first_in_stream|, returns an empty buffer and triggers QUIC_BUG. quiche::QuicheBuffer SerializeObject(const MoqtObject& message, - absl::string_view payload); + absl::string_view payload, + bool is_first_in_stream); // Build a buffer for additional payload data. quiche::QuicheBuffer SerializeObjectPayload(absl::string_view payload); quiche::QuicheBuffer SerializeClientSetup(const MoqtClientSetup& message); quiche::QuicheBuffer SerializeServerSetup(const MoqtServerSetup& message); // Returns an empty buffer if there is an illegal combination of locations. - quiche::QuicheBuffer SerializeSubscribeRequest( - const MoqtSubscribeRequest& message); + quiche::QuicheBuffer SerializeSubscribe(const MoqtSubscribe& message); quiche::QuicheBuffer SerializeSubscribeOk(const MoqtSubscribeOk& message); quiche::QuicheBuffer SerializeSubscribeError( const MoqtSubscribeError& message); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc index 9c9021ca93..0a27832260 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.cc @@ -6,19 +6,21 @@ #include +#include "quiche/quic/platform/api/quic_bug_tracker.h" + namespace moqt { std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { switch (message_type) { - case MoqtMessageType::kObjectWithPayloadLength: - return "OBJECT_WITH_LENGTH"; - case MoqtMessageType::kObjectWithoutPayloadLength: - return "OBJECT_WITHOUT_LENGTH"; + case MoqtMessageType::kObjectStream: + return "OBJECT_STREAM"; + case MoqtMessageType::kObjectPreferDatagram: + return "OBJECT_PREFER_DATAGRAM"; case MoqtMessageType::kClientSetup: return "CLIENT_SETUP"; case MoqtMessageType::kServerSetup: return "SERVER_SETUP"; - case MoqtMessageType::kSubscribeRequest: + case MoqtMessageType::kSubscribe: return "SUBSCRIBE_REQUEST"; case MoqtMessageType::kSubscribeOk: return "SUBSCRIBE_OK"; @@ -40,7 +42,64 @@ std::string MoqtMessageTypeToString(const MoqtMessageType message_type) { return "UNANNOUNCE"; case MoqtMessageType::kGoAway: return "GOAWAY"; + case MoqtMessageType::kStreamHeaderTrack: + return "STREAM_HEADER_TRACK"; + case MoqtMessageType::kStreamHeaderGroup: + return "STREAM_HEADER_GROUP"; } + return "Unknown message " + std::to_string(static_cast(message_type)); +} + +std::string MoqtForwardingPreferenceToString( + MoqtForwardingPreference preference) { + switch (preference) { + case MoqtForwardingPreference::kObject: + return "OBJECT"; + case MoqtForwardingPreference::kDatagram: + return "DATAGRAM"; + case MoqtForwardingPreference::kTrack: + return "TRACK"; + case MoqtForwardingPreference::kGroup: + return "GROUP"; + } + QUIC_BUG(quic_bug_bad_moqt_message_type_01) + << "Unknown preference " << std::to_string(static_cast(preference)); + return "Unknown preference " + std::to_string(static_cast(preference)); +} + +MoqtForwardingPreference GetForwardingPreference(MoqtMessageType type) { + switch (type) { + case MoqtMessageType::kObjectStream: + return MoqtForwardingPreference::kObject; + case MoqtMessageType::kObjectPreferDatagram: + return MoqtForwardingPreference::kDatagram; + case MoqtMessageType::kStreamHeaderTrack: + return MoqtForwardingPreference::kTrack; + case MoqtMessageType::kStreamHeaderGroup: + return MoqtForwardingPreference::kGroup; + default: + break; + } + QUIC_BUG(quic_bug_bad_moqt_message_type_02) + << "Message type does not indicate forwarding preference"; + return MoqtForwardingPreference::kObject; +}; + +MoqtMessageType GetMessageTypeForForwardingPreference( + MoqtForwardingPreference preference) { + switch (preference) { + case MoqtForwardingPreference::kObject: + return MoqtMessageType::kObjectStream; + case MoqtForwardingPreference::kDatagram: + return MoqtMessageType::kObjectPreferDatagram; + case MoqtForwardingPreference::kTrack: + return MoqtMessageType::kStreamHeaderTrack; + case MoqtForwardingPreference::kGroup: + return MoqtMessageType::kStreamHeaderGroup; + } + QUIC_BUG(quic_bug_bad_moqt_message_type_03) + << "Forwarding preference does not indicate message type"; + return MoqtMessageType::kObjectStream; } } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h index 773907b56f..9922c04b1b 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Structured data for message types in draft-ietf-moq-transport-01. +// Structured data for message types in draft-ietf-moq-transport-02. #ifndef QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_ #define QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_ @@ -27,7 +27,7 @@ inline constexpr quic::ParsedQuicVersionVector GetMoqtSupportedQuicVersions() { } enum class MoqtVersion : uint64_t { - kDraft01 = 0xff000001, + kDraft02 = 0xff000002, kUnrecognizedVersionForTests = 0xfe0000ff, }; @@ -46,9 +46,9 @@ struct QUICHE_EXPORT MoqtSessionParameters { inline constexpr size_t kMaxMessageHeaderSize = 2048; enum class QUICHE_EXPORT MoqtMessageType : uint64_t { - kObjectWithPayloadLength = 0x00, - kObjectWithoutPayloadLength = 0x02, - kSubscribeRequest = 0x03, + kObjectStream = 0x00, + kObjectPreferDatagram = 0x01, + kSubscribe = 0x03, kSubscribeOk = 0x04, kSubscribeError = 0x05, kAnnounce = 0x06, @@ -61,6 +61,18 @@ enum class QUICHE_EXPORT MoqtMessageType : uint64_t { kGoAway = 0x10, kClientSetup = 0x40, kServerSetup = 0x41, + kStreamHeaderTrack = 0x50, + kStreamHeaderGroup = 0x51, +}; + +enum class QUICHE_EXPORT MoqtError : uint64_t { + kNoError = 0x0, + kGenericError = 0x1, + kUnauthorized = 0x2, + kProtocolViolation = 0x3, + kDuplicateTrackAlias = 0x4, + kParameterLengthMismatch = 0x5, + kGoawayTimeout = 0x10, }; enum class QUICHE_EXPORT MoqtRole : uint64_t { @@ -75,17 +87,14 @@ enum class QUICHE_EXPORT MoqtSetupParameter : uint64_t { }; enum class QUICHE_EXPORT MoqtTrackRequestParameter : uint64_t { - // These two should have been deleted in draft-01. - // kGroupSequence = 0x0, - // kObjectSequence = 0x1, kAuthorizationInfo = 0x2, }; struct FullTrackName { std::string track_namespace; std::string track_name; - FullTrackName(std::string ns, std::string name) - : track_namespace(std::move(ns)), track_name(std::move(name)) {} + FullTrackName(absl::string_view ns, absl::string_view name) + : track_namespace(ns), track_name(name) {} bool operator==(const FullTrackName& other) const { return track_namespace == other.track_namespace && track_name == other.track_name; @@ -115,6 +124,17 @@ struct FullSequence { return group < other.group || (group == other.group && object < other.object); } + bool operator<=(const FullSequence& other) const { + return (group < other.group || + (group == other.group && object <= other.object)); + } + FullSequence& operator=(FullSequence other) { + group = other.group; + object = other.object; + return *this; + } + template + friend H AbslHashValue(H h, const FullSequence& m); }; template @@ -133,13 +153,25 @@ struct QUICHE_EXPORT MoqtServerSetup { std::optional role; }; +// These codes do not appear on the wire. +enum class QUICHE_EXPORT MoqtForwardingPreference : uint8_t { + kTrack = 0x0, + kGroup = 0x1, + kObject = 0x2, + kDatagram = 0x3, +}; + +// The data contained in every Object message, although the message type +// implies some of the values. |payload_length| has no value if the length +// is unknown (because it runs to the end of the stream.) struct QUICHE_EXPORT MoqtObject { - uint64_t track_id; - uint64_t group_sequence; - uint64_t object_sequence; + uint64_t subscribe_id; + uint64_t track_alias; + uint64_t group_id; + uint64_t object_id; uint64_t object_send_order; + MoqtForwardingPreference forwarding_preference; std::optional payload_length; - // Message also includes the object payload. }; enum class QUICHE_EXPORT MoqtSubscribeLocationMode : uint64_t { @@ -170,7 +202,9 @@ struct QUICHE_EXPORT MoqtSubscribeLocation { } }; -struct QUICHE_EXPORT MoqtSubscribeRequest { +struct QUICHE_EXPORT MoqtSubscribe { + uint64_t subscribe_id; + uint64_t track_alias; absl::string_view track_namespace; absl::string_view track_name; // If the mode is kNone, the these are std::nullopt. @@ -182,35 +216,36 @@ struct QUICHE_EXPORT MoqtSubscribeRequest { }; struct QUICHE_EXPORT MoqtSubscribeOk { - absl::string_view track_namespace; - absl::string_view track_name; - uint64_t track_id; + uint64_t subscribe_id; // The message uses ms, but expires is in us. quic::QuicTimeDelta expires = quic::QuicTimeDelta::FromMilliseconds(0); }; +enum class QUICHE_EXPORT SubscribeErrorCode : uint64_t { + kGenericError = 0x0, + kInvalidRange = 0x1, + kRetryTrackAlias = 0x2, +}; + struct QUICHE_EXPORT MoqtSubscribeError { - absl::string_view track_namespace; - absl::string_view track_name; - uint64_t error_code; + uint64_t subscribe_id; + SubscribeErrorCode error_code; absl::string_view reason_phrase; + uint64_t track_alias; }; struct QUICHE_EXPORT MoqtUnsubscribe { - absl::string_view track_namespace; - absl::string_view track_name; + uint64_t subscribe_id; }; struct QUICHE_EXPORT MoqtSubscribeFin { - absl::string_view track_namespace; - absl::string_view track_name; + uint64_t subscribe_id; uint64_t final_group; uint64_t final_object; }; struct QUICHE_EXPORT MoqtSubscribeRst { - absl::string_view track_namespace; - absl::string_view track_name; + uint64_t subscribe_id; uint64_t error_code; absl::string_view reason_phrase; uint64_t final_group; @@ -242,6 +277,14 @@ struct QUICHE_EXPORT MoqtGoAway { std::string MoqtMessageTypeToString(MoqtMessageType message_type); +std::string MoqtForwardingPreferenceToString( + MoqtForwardingPreference preference); + +MoqtForwardingPreference GetForwardingPreference(MoqtMessageType type); + +MoqtMessageType GetMessageTypeForForwardingPreference( + MoqtForwardingPreference preference); + } // namespace moqt #endif // QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc index 8a9213ca4f..96c8a92e0a 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.cc @@ -7,7 +7,6 @@ #include #include #include -#include #include #include @@ -41,9 +40,8 @@ void MoqtParser::ProcessData(absl::string_view data, bool fin) { // Check for early fin if (fin) { no_more_data_ = true; - if (object_metadata_.has_value() && - object_metadata_->payload_length.has_value() && - *object_metadata_->payload_length > data.length()) { + if (ObjectPayloadInProgress() && + payload_length_remaining_ > data.length()) { ParseError("End of stream before complete OBJECT PAYLOAD"); return; } @@ -57,7 +55,7 @@ void MoqtParser::ProcessData(absl::string_view data, bool fin) { // There are three cases: the parser has already delivered an OBJECT header // and is now delivering payload; part of a message is in the buffer; or // no message is in progress. - if (object_metadata_.has_value()) { + if (ObjectPayloadInProgress()) { // This is additional payload for an OBJECT. QUICHE_DCHECK(buffered_message_.empty()); if (!object_metadata_->payload_length.has_value()) { @@ -79,7 +77,7 @@ void MoqtParser::ProcessData(absl::string_view data, bool fin) { visitor_.OnObjectMessage(*object_metadata_, data.substr(0, payload_length_remaining_), true); reader->Seek(payload_length_remaining_); - object_metadata_.reset(); + payload_length_remaining_ = 0; // Expect a new object. } else if (!buffered_message_.empty()) { absl::StrAppend(&buffered_message_, data); reader.emplace(buffered_message_); @@ -92,7 +90,8 @@ void MoqtParser::ProcessData(absl::string_view data, bool fin) { size_t message_len = ProcessMessage(reader->PeekRemainingPayload(), fin); if (message_len == 0) { if (reader->BytesRemaining() > kMaxMessageHeaderSize) { - ParseError("Cannot parse non-OBJECT messages > 2KB"); + ParseError(MoqtError::kGenericError, + "Cannot parse non-OBJECT messages > 2KB"); return; } if (fin) { @@ -112,29 +111,34 @@ void MoqtParser::ProcessData(absl::string_view data, bool fin) { if (original_buffer_size > 0) { buffered_message_.erase(0, total_processed); } - if (fin && object_metadata_.has_value()) { - ParseError("Received FIN mid-payload"); - } } size_t MoqtParser::ProcessMessage(absl::string_view data, bool fin) { uint64_t value; quic::QuicDataReader reader(data); + if (ObjectStreamInitialized() && !ObjectPayloadInProgress()) { + // This is a follow-on object in a stream. + return ProcessObject(reader, + GetMessageTypeForForwardingPreference( + object_metadata_->forwarding_preference), + fin); + } if (!reader.ReadVarInt62(&value)) { return 0; } auto type = static_cast(value); switch (type) { - case MoqtMessageType::kObjectWithPayloadLength: - return ProcessObject(reader, true, fin); - case MoqtMessageType::kObjectWithoutPayloadLength: - return ProcessObject(reader, false, fin); + case MoqtMessageType::kObjectStream: + case MoqtMessageType::kObjectPreferDatagram: + case MoqtMessageType::kStreamHeaderTrack: + case MoqtMessageType::kStreamHeaderGroup: + return ProcessObject(reader, type, fin); case MoqtMessageType::kClientSetup: return ProcessClientSetup(reader); case MoqtMessageType::kServerSetup: return ProcessServerSetup(reader); - case MoqtMessageType::kSubscribeRequest: - return ProcessSubscribeRequest(reader); + case MoqtMessageType::kSubscribe: + return ProcessSubscribe(reader); case MoqtMessageType::kSubscribeOk: return ProcessSubscribeOk(reader); case MoqtMessageType::kSubscribeError: @@ -161,39 +165,84 @@ size_t MoqtParser::ProcessMessage(absl::string_view data, bool fin) { } } -size_t MoqtParser::ProcessObject(quic::QuicDataReader& reader, bool has_length, - bool fin) { - QUICHE_DCHECK(!object_metadata_.has_value()); - object_metadata_ = MoqtObject(); - uint64_t length; - if (!reader.ReadVarInt62(&object_metadata_->track_id) || - !reader.ReadVarInt62(&object_metadata_->group_sequence) || - !reader.ReadVarInt62(&object_metadata_->object_sequence) || - !reader.ReadVarInt62(&object_metadata_->object_send_order) || - (has_length && !reader.ReadVarInt62(&length))) { - object_metadata_.reset(); - return 0; +size_t MoqtParser::ProcessObject(quic::QuicDataReader& reader, + MoqtMessageType type, bool fin) { + size_t processed_data; + QUICHE_DCHECK(!ObjectPayloadInProgress()); + if (!ObjectStreamInitialized()) { + // nothing has been processed on the stream. + object_metadata_ = MoqtObject(); + if (!reader.ReadVarInt62(&object_metadata_->subscribe_id) || + !reader.ReadVarInt62(&object_metadata_->track_alias)) { + object_metadata_.reset(); + return 0; + } + if (type != MoqtMessageType::kStreamHeaderTrack && + !reader.ReadVarInt62(&object_metadata_->group_id)) { + object_metadata_.reset(); + return 0; + } + if (type != MoqtMessageType::kStreamHeaderTrack && + type != MoqtMessageType::kStreamHeaderGroup && + !reader.ReadVarInt62(&object_metadata_->object_id)) { + object_metadata_.reset(); + return 0; + } + if (!reader.ReadVarInt62(&object_metadata_->object_send_order)) { + object_metadata_.reset(); + return 0; + } + object_metadata_->forwarding_preference = GetForwardingPreference(type); } - if (has_length) { - object_metadata_->payload_length = length; + // At this point, enough data has been processed to store in object_metadata_, + // even if there's nothing else in the buffer. + processed_data = reader.PreviouslyReadPayload().length(); + QUICHE_DCHECK(payload_length_remaining_ == 0); + switch (type) { + case MoqtMessageType::kStreamHeaderTrack: + if (!reader.ReadVarInt62(&object_metadata_->group_id)) { + return processed_data; + } + [[fallthrough]]; + case MoqtMessageType::kStreamHeaderGroup: { + uint64_t length; + if (!reader.ReadVarInt62(&object_metadata_->object_id) || + !reader.ReadVarInt62(&length)) { + return processed_data; + } + object_metadata_->payload_length = length; + break; + } + default: + break; } - bool received_complete_message = - (fin && !has_length) || - (has_length && - *object_metadata_->payload_length <= reader.BytesRemaining()); - size_t payload_to_draw = (!has_length || *object_metadata_->payload_length >= - reader.BytesRemaining()) - ? reader.BytesRemaining() - : *object_metadata_->payload_length; + bool has_length = object_metadata_->payload_length.has_value(); + bool received_complete_message = false; + size_t payload_to_draw = reader.BytesRemaining(); + if (fin && has_length && + *object_metadata_->payload_length > reader.BytesRemaining()) { + ParseError("Received FIN mid-payload"); + return processed_data; + } + received_complete_message = + fin || (has_length && + *object_metadata_->payload_length <= reader.BytesRemaining()); + if (received_complete_message && has_length && + *object_metadata_->payload_length < reader.BytesRemaining()) { + payload_to_draw = *object_metadata_->payload_length; + } + // The error case where there's a fin before the explicit length is complete + // is handled in ProcessData() in two separate places. Even though the + // message is "done" if fin regardless of has_length, it's bad to report to + // the application that the object is done if it hasn't reached the promised + // length. visitor_.OnObjectMessage( *object_metadata_, reader.PeekRemainingPayload().substr(0, payload_to_draw), received_complete_message); - if (received_complete_message) { - object_metadata_.reset(); - } reader.Seek(payload_to_draw); - payload_length_remaining_ = length - payload_to_draw; + payload_length_remaining_ = + has_length ? *object_metadata_->payload_length - payload_to_draw : 0; return reader.PreviouslyReadPayload().length(); } @@ -302,38 +351,34 @@ size_t MoqtParser::ProcessServerSetup(quic::QuicDataReader& reader) { return reader.PreviouslyReadPayload().length(); } -size_t MoqtParser::ProcessSubscribeRequest(quic::QuicDataReader& reader) { - MoqtSubscribeRequest subscribe_request; - if (!reader.ReadStringPieceVarInt62(&subscribe_request.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_request.track_name)) { - return 0; - } - if (!ReadLocation(reader, subscribe_request.start_group)) { +size_t MoqtParser::ProcessSubscribe(quic::QuicDataReader& reader) { + MoqtSubscribe subscribe_request; + if (!reader.ReadVarInt62(&subscribe_request.subscribe_id) || + !reader.ReadVarInt62(&subscribe_request.track_alias) || + !reader.ReadStringPieceVarInt62(&subscribe_request.track_namespace) || + !reader.ReadStringPieceVarInt62(&subscribe_request.track_name) || + !ReadLocation(reader, subscribe_request.start_group)) { return 0; } if (!subscribe_request.start_group.has_value()) { - ParseError("START_GROUP must not be None in SUBSCRIBE_REQUEST"); + ParseError("START_GROUP must not be None in SUBSCRIBE"); return 0; } if (!ReadLocation(reader, subscribe_request.start_object)) { return 0; } if (!subscribe_request.start_object.has_value()) { - ParseError("START_OBJECT must not be None in SUBSCRIBE_REQUEST"); + ParseError("START_OBJECT must not be None in SUBSCRIBE"); return 0; } - if (!ReadLocation(reader, subscribe_request.end_group)) { - return 0; - } - if (!ReadLocation(reader, subscribe_request.end_object)) { + if (!ReadLocation(reader, subscribe_request.end_group) || + !ReadLocation(reader, subscribe_request.end_object)) { return 0; } if (subscribe_request.end_group.has_value() != subscribe_request.end_object.has_value()) { ParseError( - "SUBSCRIBE_REQUEST end_group and end_object must be both None " + "SUBSCRIBE end_group and end_object must be both None " "or both non_None"); return 0; } @@ -363,23 +408,15 @@ size_t MoqtParser::ProcessSubscribeRequest(quic::QuicDataReader& reader) { break; } } - visitor_.OnSubscribeRequestMessage(subscribe_request); + visitor_.OnSubscribeMessage(subscribe_request); return reader.PreviouslyReadPayload().length(); } size_t MoqtParser::ProcessSubscribeOk(quic::QuicDataReader& reader) { MoqtSubscribeOk subscribe_ok; - if (!reader.ReadStringPieceVarInt62(&subscribe_ok.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_ok.track_name)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_ok.track_id)) { - return 0; - } uint64_t milliseconds; - if (!reader.ReadVarInt62(&milliseconds)) { + if (!reader.ReadVarInt62(&subscribe_ok.subscribe_id) || + !reader.ReadVarInt62(&milliseconds)) { return 0; } subscribe_ok.expires = quic::QuicTimeDelta::FromMilliseconds(milliseconds); @@ -389,28 +426,21 @@ size_t MoqtParser::ProcessSubscribeOk(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribeError(quic::QuicDataReader& reader) { MoqtSubscribeError subscribe_error; - if (!reader.ReadStringPieceVarInt62(&subscribe_error.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_error.track_name)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_error.error_code)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_error.reason_phrase)) { + uint64_t error_code; + if (!reader.ReadVarInt62(&subscribe_error.subscribe_id) || + !reader.ReadVarInt62(&error_code) || + !reader.ReadStringPieceVarInt62(&subscribe_error.reason_phrase) || + !reader.ReadVarInt62(&subscribe_error.track_alias)) { return 0; } + subscribe_error.error_code = static_cast(error_code); visitor_.OnSubscribeErrorMessage(subscribe_error); return reader.PreviouslyReadPayload().length(); } size_t MoqtParser::ProcessUnsubscribe(quic::QuicDataReader& reader) { MoqtUnsubscribe unsubscribe; - if (!reader.ReadStringPieceVarInt62(&unsubscribe.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&unsubscribe.track_name)) { + if (!reader.ReadVarInt62(&unsubscribe.subscribe_id)) { return 0; } visitor_.OnUnsubscribeMessage(unsubscribe); @@ -419,16 +449,9 @@ size_t MoqtParser::ProcessUnsubscribe(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribeFin(quic::QuicDataReader& reader) { MoqtSubscribeFin subscribe_fin; - if (!reader.ReadStringPieceVarInt62(&subscribe_fin.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_fin.track_name)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_fin.final_group)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_fin.final_object)) { + if (!reader.ReadVarInt62(&subscribe_fin.subscribe_id) || + !reader.ReadVarInt62(&subscribe_fin.final_group) || + !reader.ReadVarInt62(&subscribe_fin.final_object)) { return 0; } visitor_.OnSubscribeFinMessage(subscribe_fin); @@ -437,22 +460,11 @@ size_t MoqtParser::ProcessSubscribeFin(quic::QuicDataReader& reader) { size_t MoqtParser::ProcessSubscribeRst(quic::QuicDataReader& reader) { MoqtSubscribeRst subscribe_rst; - if (!reader.ReadStringPieceVarInt62(&subscribe_rst.track_namespace)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_rst.track_name)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_rst.error_code)) { - return 0; - } - if (!reader.ReadStringPieceVarInt62(&subscribe_rst.reason_phrase)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_rst.final_group)) { - return 0; - } - if (!reader.ReadVarInt62(&subscribe_rst.final_object)) { + if (!reader.ReadVarInt62(&subscribe_rst.subscribe_id) || + !reader.ReadVarInt62(&subscribe_rst.error_code) || + !reader.ReadStringPieceVarInt62(&subscribe_rst.reason_phrase) || + !reader.ReadVarInt62(&subscribe_rst.final_group) || + !reader.ReadVarInt62(&subscribe_rst.final_object)) { return 0; } visitor_.OnSubscribeRstMessage(subscribe_rst); @@ -535,12 +547,16 @@ size_t MoqtParser::ProcessGoAway(quic::QuicDataReader& reader) { } void MoqtParser::ParseError(absl::string_view reason) { + ParseError(MoqtError::kProtocolViolation, reason); +} + +void MoqtParser::ParseError(MoqtError error_code, absl::string_view reason) { if (parsing_error_) { return; // Don't send multiple parse errors. } no_more_data_ = true; parsing_error_ = true; - visitor_.OnParsingError(reason); + visitor_.OnParsingError(error_code, reason); } bool MoqtParser::ReadVarIntPieceVarInt62(quic::QuicDataReader& reader, @@ -582,7 +598,7 @@ bool MoqtParser::ReadLocation(quic::QuicDataReader& reader, loc = MoqtSubscribeLocation(false, -1 * static_cast(ui64)); break; case MoqtSubscribeLocationMode::kRelativeNext: - loc = MoqtSubscribeLocation(false, static_cast(ui64)); + loc = MoqtSubscribeLocation(false, static_cast(ui64) + 1); break; default: ParseError("Unknown location mode"); @@ -602,7 +618,8 @@ bool MoqtParser::ReadParameter(quic::QuicDataReader& reader, uint64_t& type, bool MoqtParser::StringViewToVarInt(absl::string_view& sv, uint64_t& vi) { quic::QuicDataReader reader(sv); if (static_cast(reader.PeekVarInt62Length()) != sv.length()) { - ParseError("Parameter length does not match varint encoding"); + ParseError(MoqtError::kParameterLengthMismatch, + "Parameter length does not match varint encoding"); return false; } reader.ReadVarInt62(&vi); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h index 9dd63b5a25..3bb7f47f6e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_parser.h @@ -34,8 +34,7 @@ class QUICHE_EXPORT MoqtParserVisitor { // parser retains ownership of the memory. virtual void OnClientSetupMessage(const MoqtClientSetup& message) = 0; virtual void OnServerSetupMessage(const MoqtServerSetup& message) = 0; - virtual void OnSubscribeRequestMessage( - const MoqtSubscribeRequest& message) = 0; + virtual void OnSubscribeMessage(const MoqtSubscribe& message) = 0; virtual void OnSubscribeOkMessage(const MoqtSubscribeOk& message) = 0; virtual void OnSubscribeErrorMessage(const MoqtSubscribeError& message) = 0; virtual void OnUnsubscribeMessage(const MoqtUnsubscribe& message) = 0; @@ -47,7 +46,7 @@ class QUICHE_EXPORT MoqtParserVisitor { virtual void OnUnannounceMessage(const MoqtUnannounce& message) = 0; virtual void OnGoAwayMessage(const MoqtGoAway& message) = 0; - virtual void OnParsingError(absl::string_view reason) = 0; + virtual void OnParsingError(MoqtError code, absl::string_view reason) = 0; }; class QUICHE_EXPORT MoqtParser { @@ -63,6 +62,8 @@ class QUICHE_EXPORT MoqtParser { // All bytes can be freed. Calls OnParsingError() when there is a parsing // error. // Any calls after sending |fin| = true will be ignored. + // TODO(martinduke): Figure out what has to happen if the message arrives via + // datagram rather than a stream. void ProcessData(absl::string_view data, bool fin); private: @@ -75,10 +76,11 @@ class QUICHE_EXPORT MoqtParser { // structs, and call the relevant visitor function for further action. Returns // the number of bytes consumed if the message is complete; returns 0 // otherwise. - size_t ProcessObject(quic::QuicDataReader& reader, bool has_length, bool fin); + size_t ProcessObject(quic::QuicDataReader& reader, MoqtMessageType type, + bool fin); size_t ProcessClientSetup(quic::QuicDataReader& reader); size_t ProcessServerSetup(quic::QuicDataReader& reader); - size_t ProcessSubscribeRequest(quic::QuicDataReader& reader); + size_t ProcessSubscribe(quic::QuicDataReader& reader); size_t ProcessSubscribeOk(quic::QuicDataReader& reader); size_t ProcessSubscribeError(quic::QuicDataReader& reader); size_t ProcessUnsubscribe(quic::QuicDataReader& reader); @@ -90,7 +92,9 @@ class QUICHE_EXPORT MoqtParser { size_t ProcessUnannounce(quic::QuicDataReader& reader); size_t ProcessGoAway(quic::QuicDataReader& reader); + // If |error| is not provided, assumes kProtocolViolation. void ParseError(absl::string_view reason); + void ParseError(MoqtError error, absl::string_view reason); // Reads an integer whose length is specified by a preceding VarInt62 and // returns it in |result|. Returns false if parsing fails. @@ -106,6 +110,21 @@ class QUICHE_EXPORT MoqtParser { // string_view is not exactly the right length. bool StringViewToVarInt(absl::string_view& sv, uint64_t& vi); + // Simplify understanding of state. + // Returns true if the stream has delivered all object metadata common to all + // objects on that stream. + bool ObjectStreamInitialized() const { return object_metadata_.has_value(); } + // Returns true if the stream has delivered all metadata but not all payload + // for the most recent object. + bool ObjectPayloadInProgress() const { + return (object_metadata_.has_value() && + (object_metadata_->forwarding_preference == + MoqtForwardingPreference::kObject || + object_metadata_->forwarding_preference == + MoqtForwardingPreference::kDatagram || + payload_length_remaining_ > 0)); + } + MoqtParserVisitor& visitor_; bool uses_web_transport_; bool no_more_data_ = false; // Fatal error or fin. No more parsing. @@ -114,8 +133,17 @@ class QUICHE_EXPORT MoqtParser { std::string buffered_message_; // Metadata for an object which is delivered in parts. + // If object_metadata_ is nullopt, nothing has been processed on the stream. + // If object_metadata_ exists but payload_length is nullopt or + // payload_length_remaining_ is nonzero, the object payload is in mid- + // delivery. + // If object_metadata_ exists and payload_length_remaining_ is zero, an object + // has been completely delivered and the next object header on the stream has + // not been delivered. + // Use ObjectStreamInitialized() and ObjectPayloadInProgress() to keep the + // state straight. std::optional object_metadata_ = std::nullopt; - size_t payload_length_remaining_; + size_t payload_length_remaining_ = 0; bool processing_ = false; // True if currently in ProcessData(), to prevent // re-entrancy. diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc index b17a40f841..11feb9ef48 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.cc @@ -12,6 +12,7 @@ #include #include "absl/algorithm/container.h" +#include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_types.h" @@ -30,11 +31,6 @@ namespace moqt { using ::quic::Perspective; -constexpr uint64_t kMoqtErrorTrackDoesntExist = 1; -constexpr uint64_t kMoqtErrorObjectDoesntExist = 2; - -constexpr int kMaxBufferedObjects = 1000; - void MoqtSession::OnSessionReady() { QUICHE_DLOG(INFO) << ENDPOINT << "Underlying session ready"; if (parameters_.perspective == Perspective::IS_SERVER) { @@ -44,7 +40,7 @@ void MoqtSession::OnSessionReady() { webtransport::Stream* control_stream = session_->OpenOutgoingBidirectionalStream(); if (control_stream == nullptr) { - Error("Unable to open a control stream"); + Error(MoqtError::kGenericError, "Unable to open a control stream"); return; } control_stream->SetVisitor(std::make_unique( @@ -60,7 +56,7 @@ void MoqtSession::OnSessionReady() { quiche::QuicheBuffer serialized_setup = framer_.SerializeClientSetup(setup); bool success = control_stream->Write(serialized_setup.AsStringView()); if (!success) { - Error("Failed to write client SETUP message"); + Error(MoqtError::kGenericError, "Failed to write client SETUP message"); return; } QUIC_DLOG(INFO) << ENDPOINT << "Send the SETUP message"; @@ -81,6 +77,10 @@ void MoqtSession::OnSessionClosed(webtransport::SessionErrorCode, void MoqtSession::OnIncomingBidirectionalStreamAvailable() { while (webtransport::Stream* stream = session_->AcceptIncomingBidirectionalStream()) { + if (control_stream_.has_value()) { + Error(MoqtError::kProtocolViolation, "Bidirectional stream already open"); + return; + } stream->SetVisitor(std::make_unique(this, stream)); stream->visitor()->OnCanRead(); } @@ -93,23 +93,21 @@ void MoqtSession::OnIncomingUnidirectionalStreamAvailable() { } } -void MoqtSession::Error(absl::string_view error) { +void MoqtSession::Error(MoqtError code, absl::string_view error) { if (!error_.empty()) { // Avoid erroring out twice. return; } - QUICHE_DLOG(INFO) << ENDPOINT - << "MOQT session closed with message: " << error; + QUICHE_DLOG(INFO) << ENDPOINT << "MOQT session closed with code: " + << static_cast(code) << " and message: " << error; error_ = std::string(error); - // TODO(vasilvv): figure out the error code. - session_->CloseSession(1, error); + session_->CloseSession(static_cast(code), error); std::move(session_terminated_callback_)(error); } void MoqtSession::AddLocalTrack(const FullTrackName& full_track_name, LocalTrack::Visitor* visitor) { - local_tracks_.try_emplace(full_track_name, full_track_name, - next_track_alias_++, visitor); + local_tracks_.try_emplace(full_track_name, full_track_name, visitor); } // TODO: Create state that allows ANNOUNCE_OK/ERROR on spurious namespaces to @@ -126,7 +124,7 @@ void MoqtSession::Announce(absl::string_view track_namespace, bool success = session_->GetStreamById(*control_stream_) ->Write(framer_.SerializeAnnounce(message).AsStringView()); if (!success) { - Error("Failed to write ANNOUNCE message"); + Error(MoqtError::kGenericError, "Failed to write ANNOUNCE message"); return; } QUIC_DLOG(INFO) << ENDPOINT << "Sent ANNOUNCE message for " @@ -144,7 +142,7 @@ bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, uint64_t start_group, uint64_t start_object, RemoteTrack::Visitor* visitor, absl::string_view auth_info) { - MoqtSubscribeRequest message; + MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; message.start_group = MoqtSubscribeLocation(true, start_group); @@ -171,7 +169,7 @@ bool MoqtSession::SubscribeAbsolute(absl::string_view track_namespace, QUIC_DLOG(ERROR) << "Subscription end is before beginning"; return false; } - MoqtSubscribeRequest message; + MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; message.start_group = MoqtSubscribeLocation(true, start_group); @@ -189,7 +187,7 @@ bool MoqtSession::SubscribeRelative(absl::string_view track_namespace, int64_t start_object, RemoteTrack::Visitor* visitor, absl::string_view auth_info) { - MoqtSubscribeRequest message; + MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; message.start_group = MoqtSubscribeLocation(false, start_group); @@ -206,7 +204,7 @@ bool MoqtSession::SubscribeCurrentGroup(absl::string_view track_namespace, absl::string_view name, RemoteTrack::Visitor* visitor, absl::string_view auth_info) { - MoqtSubscribeRequest message; + MoqtSubscribe message; message.track_namespace = track_namespace; message.track_name = name; // First object of current group. @@ -220,21 +218,31 @@ bool MoqtSession::SubscribeCurrentGroup(absl::string_view track_namespace, return Subscribe(message, visitor); } -bool MoqtSession::Subscribe(const MoqtSubscribeRequest& message, +bool MoqtSession::Subscribe(MoqtSubscribe& message, RemoteTrack::Visitor* visitor) { // TODO(martinduke): support authorization info - bool success = - session_->GetStreamById(*control_stream_) - ->Write(framer_.SerializeSubscribeRequest(message).AsStringView()); - if (!success) { - Error("Failed to write SUBSCRIBE_REQUEST message"); - return false; - } - QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE_REQUEST message for " - << message.track_namespace << ":" << message.track_name; + message.subscribe_id = next_subscribe_id_++; FullTrackName ftn(std::string(message.track_namespace), std::string(message.track_name)); - remote_tracks_.try_emplace(ftn, ftn, visitor); + auto it = remote_track_aliases_.find(ftn); + if (it != remote_track_aliases_.end()) { + message.track_alias = it->second; + if (message.track_alias >= next_remote_track_alias_) { + next_remote_track_alias_ = message.track_alias + 1; + } + } else { + message.track_alias = next_remote_track_alias_++; + } + bool success = + session_->GetStreamById(*control_stream_) + ->Write(framer_.SerializeSubscribe(message).AsStringView()); + if (!success) { + Error(MoqtError::kGenericError, "Failed to write SUBSCRIBE message"); + return false; + } + QUIC_DLOG(INFO) << ENDPOINT << "Sent SUBSCRIBE message for " + << message.track_namespace << ":" << message.track_name; + active_subscribes_.try_emplace(message.subscribe_id, message, visitor); return true; } @@ -251,55 +259,87 @@ std::optional MoqtSession::OpenUnidirectionalStream() { return new_stream->GetStreamId(); } -// increment object_sequence or group_sequence depending on |start_new_group| -void MoqtSession::PublishObjectToStream(webtransport::StreamId stream_id, - FullTrackName full_track_name, - bool start_new_group, - absl::string_view payload) { - // TODO: check that the peer is subscribed to the next sequence. - webtransport::Stream* stream = session_->GetStreamById(stream_id); - if (stream == nullptr) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT to nonexistent stream"; - return; +bool MoqtSession::PublishObject(FullTrackName& full_track_name, + uint64_t group_id, uint64_t object_id, + uint64_t object_send_order, + MoqtForwardingPreference forwarding_preference, + absl::string_view payload, + std::optional payload_length, + bool end_of_stream) { + if (payload_length.has_value() && *payload_length < payload.length()) { + QUICHE_DLOG(ERROR) << ENDPOINT << "Payload too short"; + return false; } auto track_it = local_tracks_.find(full_track_name); if (track_it == local_tracks_.end()) { QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT for nonexistent track"; - return; + return false; + } + LocalTrack& track = track_it->second; + track.SentSequence(FullSequence(group_id, object_id)); + std::vector subscriptions = + track.ShouldSend({group_id, object_id}); + if (subscriptions.empty()) { + return true; } MoqtObject object; - LocalTrack& track = track_it->second; - object.track_id = track.track_alias(); - FullSequence& next_sequence = track.next_sequence_mutable(); - object.group_sequence = next_sequence.group; - if (start_new_group) { - ++object.group_sequence; - object.object_sequence = 0; - } else { - object.object_sequence = next_sequence.object; - } - next_sequence.group = object.group_sequence; - next_sequence.object = object.object_sequence + 1; - if (!track.ShouldSend(object.group_sequence, object.object_sequence)) { - QUICHE_LOG(INFO) << ENDPOINT << "Not sending object " + QUICHE_DCHECK(track.track_alias().has_value()); + object.track_alias = *track.track_alias(); + object.group_id = group_id; + object.object_id = object_id; + object.object_send_order = object_send_order; + object.forwarding_preference = forwarding_preference; + object.payload_length = payload_length; + int failures = 0; + quiche::StreamWriteOptions write_options; + write_options.set_send_fin(end_of_stream); + for (auto subscription : subscriptions) { + // TODO: kPreferDatagram should bypass stream stuff. For now, send it on the + // stream. + bool new_stream = false; + std::optional stream_id = + subscription->GetStreamForSequence({group_id, object_id}, + forwarding_preference); + if (!stream_id.has_value()) { + new_stream = true; + stream_id = OpenUnidirectionalStream(); + if (!stream_id.has_value()) { + QUICHE_DLOG(ERROR) << ENDPOINT + << "Sending OBJECT to nonexistent stream"; + ++failures; + continue; + } + if (!end_of_stream) { + subscription->AddStream(forwarding_preference, *stream_id, group_id, + object_id); + } + } + webtransport::Stream* stream = session_->GetStreamById(*stream_id); + if (stream == nullptr) { + QUICHE_DLOG(ERROR) << ENDPOINT << "Sending OBJECT to nonexistent stream " + << *stream_id; + ++failures; + continue; + } + object.subscribe_id = subscription->subscribe_id(); + if (quiche::WriteIntoStream( + *stream, + framer_.SerializeObject(object, payload, new_stream).AsStringView(), + write_options) != absl::OkStatus()) { + QUICHE_DLOG(ERROR) << ENDPOINT << "Failed to write OBJECT message"; + ++failures; + continue; + } + QUICHE_LOG(INFO) << ENDPOINT << "Sending object " << full_track_name.track_namespace << ":" << full_track_name.track_name << " with sequence " - << object.group_sequence << ":" << object.object_sequence - << " because peer is not subscribed"; - return; + << object.group_id << ":" << object.object_id + << " on stream " << *stream_id; + if (end_of_stream && !new_stream) { + subscription->RemoveStream(forwarding_preference, group_id, object_id); + } } - object.object_send_order = 0; - object.payload_length = payload.size(); - bool success = - stream->Write(framer_.SerializeObject(object, payload).AsStringView()); - if (!success) { - QUICHE_DLOG(ERROR) << ENDPOINT << "Failed to write OBJECT message"; - return; - } - QUICHE_LOG(INFO) << ENDPOINT << "Sending object " - << full_track_name.track_namespace << ":" - << full_track_name.track_name << " with sequence " - << object.group_sequence << ":" << object.object_sequence; + return (failures == 0); } void MoqtSession::Stream::OnCanRead() { @@ -316,6 +356,7 @@ void MoqtSession::Stream::OnResetStreamReceived( webtransport::StreamErrorCode error) { if (is_control_stream_.has_value() && *is_control_stream_) { session_->Error( + MoqtError::kProtocolViolation, absl::StrCat("Control stream reset with error code ", error)); } } @@ -323,6 +364,7 @@ void MoqtSession::Stream::OnStopSendingReceived( webtransport::StreamErrorCode error) { if (is_control_stream_.has_value() && *is_control_stream_) { session_->Error( + MoqtError::kProtocolViolation, absl::StrCat("Control stream reset with error code ", error)); } } @@ -331,18 +373,21 @@ void MoqtSession::Stream::OnObjectMessage(const MoqtObject& message, absl::string_view payload, bool end_of_message) { if (is_control_stream_ == true) { - session_->Error("Received OBJECT message on control stream"); + session_->Error(MoqtError::kProtocolViolation, + "Received OBJECT message on control stream"); return; } - QUICHE_DLOG(INFO) << ENDPOINT << "Received OBJECT message on stream " - << stream_->GetStreamId() << " for track alias " - << message.track_id << " with sequence " - << message.group_sequence << ":" << message.object_sequence - << " length " << payload.size() << " explicit length " - << (message.payload_length.has_value() - ? (int)*message.payload_length - : -1) - << (end_of_message ? "F" : ""); + QUICHE_DLOG(INFO) + << ENDPOINT << "Received OBJECT message on stream " + << stream_->GetStreamId() << " for subscribe_id " << message.subscribe_id + << " for track alias " << message.track_alias << " with sequence " + << message.group_id << ":" << message.object_id << " send_order " + << message.object_send_order << " forwarding_preference " + << MoqtForwardingPreferenceToString(message.forwarding_preference) + << " length " << payload.size() << " explicit length " + << (message.payload_length.has_value() ? (int)*message.payload_length + : -1) + << (end_of_message ? "F" : ""); if (!session_->parameters_.deliver_partial_objects) { if (!end_of_message) { // Buffer partial object. absl::StrAppend(&partial_object_, payload); @@ -353,33 +398,29 @@ void MoqtSession::Stream::OnObjectMessage(const MoqtObject& message, payload = absl::string_view(partial_object_); } } - auto it = session_->tracks_by_alias_.find(message.track_id); - if (it == session_->tracks_by_alias_.end()) { - // No SUBSCRIBE_OK received with this alias, buffer it. - auto it2 = session_->object_queue_.find(message.track_id); - std::vector* queue; - if (it2 == session_->object_queue_.end()) { - queue = &session_->object_queue_[message.track_id]; - } else { - queue = &it2->second; - } - if (session_->num_buffered_objects_ >= kMaxBufferedObjects) { - session_->num_buffered_objects_++; - session_->Error("Too many buffered objects"); + auto it = session_->remote_tracks_.find(message.track_alias); + RemoteTrack::Visitor* visitor = nullptr; + absl::string_view track_namespace; + absl::string_view track_name; + if (it == session_->remote_tracks_.end()) { + // SUBSCRIBE_OK has not arrived yet, but deliver it. + auto subscribe_it = session_->active_subscribes_.find(message.subscribe_id); + if (subscribe_it == session_->active_subscribes_.end()) { return; } - queue->push_back(BufferedObject(stream_->GetStreamId(), message, payload, - end_of_message)); - QUIC_DLOG(INFO) << ENDPOINT << "Buffering OBJECT for track alias " - << message.track_id; - return; + visitor = subscribe_it->second.visitor; + track_namespace = subscribe_it->second.message.track_namespace; + track_name = subscribe_it->second.message.track_name; + } else { + visitor = it->second.visitor(); + track_namespace = it->second.full_track_name().track_namespace; + track_name = it->second.full_track_name().track_name; } - RemoteTrack* subscription = it->second; - if (subscription->visitor() != nullptr) { - subscription->visitor()->OnObjectFragment( - subscription->full_track_name(), stream_->GetStreamId(), - message.group_sequence, message.object_sequence, - message.object_send_order, payload, end_of_message); + if (visitor != nullptr) { + visitor->OnObjectFragment( + FullTrackName(track_namespace, track_name), message.group_id, + message.object_id, message.object_send_order, + message.forwarding_preference, payload, end_of_message); } partial_object_.clear(); } @@ -387,19 +428,23 @@ void MoqtSession::Stream::OnObjectMessage(const MoqtObject& message, void MoqtSession::Stream::OnClientSetupMessage(const MoqtClientSetup& message) { if (is_control_stream_.has_value()) { if (!*is_control_stream_) { - session_->Error("Received SETUP on non-control stream"); + session_->Error(MoqtError::kProtocolViolation, + "Received SETUP on non-control stream"); return; } } else { is_control_stream_ = true; } if (perspective() == Perspective::IS_CLIENT) { - session_->Error("Received CLIENT_SETUP from server"); + session_->Error(MoqtError::kProtocolViolation, + "Received CLIENT_SETUP from server"); return; } if (absl::c_find(message.supported_versions, session_->parameters_.version) == message.supported_versions.end()) { - session_->Error(absl::StrCat("Version mismatch: expected 0x", + // TODO(martinduke): Is this the right error code? See issue #346. + session_->Error(MoqtError::kProtocolViolation, + absl::StrCat("Version mismatch: expected 0x", absl::Hex(session_->parameters_.version))); return; } @@ -411,7 +456,8 @@ void MoqtSession::Stream::OnClientSetupMessage(const MoqtClientSetup& message) { bool success = stream_->Write( session_->framer_.SerializeServerSetup(response).AsStringView()); if (!success) { - session_->Error("Failed to write server SETUP message"); + session_->Error(MoqtError::kGenericError, + "Failed to write server SETUP message"); return; } QUIC_DLOG(INFO) << ENDPOINT << "Sent the SETUP message"; @@ -423,18 +469,22 @@ void MoqtSession::Stream::OnClientSetupMessage(const MoqtClientSetup& message) { void MoqtSession::Stream::OnServerSetupMessage(const MoqtServerSetup& message) { if (is_control_stream_.has_value()) { if (!*is_control_stream_) { - session_->Error("Received SETUP on non-control stream"); + session_->Error(MoqtError::kProtocolViolation, + "Received SETUP on non-control stream"); return; } } else { is_control_stream_ = true; } if (perspective() == Perspective::IS_SERVER) { - session_->Error("Received SERVER_SETUP from client"); + session_->Error(MoqtError::kProtocolViolation, + "Received SERVER_SETUP from client"); return; } if (message.selected_version != session_->parameters_.version) { - session_->Error(absl::StrCat("Version mismatch: expected 0x", + // TODO(martinduke): Is this the right error code? See issue #346. + session_->Error(MoqtError::kProtocolViolation, + absl::StrCat("Version mismatch: expected 0x", absl::Hex(session_->parameters_.version))); return; } @@ -443,29 +493,30 @@ void MoqtSession::Stream::OnServerSetupMessage(const MoqtServerSetup& message) { std::move(session_->session_established_callback_)(); } -void MoqtSession::Stream::SendSubscribeError( - const MoqtSubscribeRequest& message, uint64_t error_code, - absl::string_view reason_phrase) { +void MoqtSession::Stream::SendSubscribeError(const MoqtSubscribe& message, + SubscribeErrorCode error_code, + absl::string_view reason_phrase, + uint64_t track_alias) { MoqtSubscribeError subscribe_error; - subscribe_error.track_namespace = message.track_namespace; - subscribe_error.track_name = message.track_name; + subscribe_error.subscribe_id = message.subscribe_id; subscribe_error.error_code = error_code; subscribe_error.reason_phrase = reason_phrase; + subscribe_error.track_alias = track_alias; bool success = stream_->Write(session_->framer_.SerializeSubscribeError(subscribe_error) .AsStringView()); if (!success) { - session_->Error("Failed to write SUBSCRIBE_ERROR message"); + session_->Error(MoqtError::kGenericError, + "Failed to write SUBSCRIBE_ERROR message"); } } -void MoqtSession::Stream::OnSubscribeRequestMessage( - const MoqtSubscribeRequest& message) { +void MoqtSession::Stream::OnSubscribeMessage(const MoqtSubscribe& message) { std::string reason_phrase = ""; if (!CheckIfIsControlStream()) { return; } - QUIC_DLOG(INFO) << ENDPOINT << "Received a SUBSCRIBE_REQUEST for " + QUIC_DLOG(INFO) << ENDPOINT << "Received a SUBSCRIBE for " << message.track_namespace << ":" << message.track_name; auto it = session_->local_tracks_.find(FullTrackName( std::string(message.track_namespace), std::string(message.track_name))); @@ -473,96 +524,94 @@ void MoqtSession::Stream::OnSubscribeRequestMessage( QUIC_DLOG(INFO) << ENDPOINT << "Rejected because " << message.track_namespace << ":" << message.track_name << " does not exist"; - SendSubscribeError(message, kMoqtErrorTrackDoesntExist, - "Track does not exist"); + SendSubscribeError(message, SubscribeErrorCode::kGenericError, + "Track does not exist", message.track_alias); return; } LocalTrack& track = it->second; + if ((track.track_alias().has_value() && + message.track_alias != *track.track_alias()) || + session_->used_track_aliases_.contains(message.track_alias)) { + // Propose a different track_alias. + SendSubscribeError(message, SubscribeErrorCode::kRetryTrackAlias, + "Track alias already exists", + session_->next_local_track_alias_++); + return; + } else { // Use client-provided alias. + track.set_track_alias(message.track_alias); + if (message.track_alias >= session_->next_local_track_alias_) { + session_->next_local_track_alias_ = message.track_alias + 1; + } + session_->used_track_aliases_.insert(message.track_alias); + } std::optional start = session_->LocationToAbsoluteNumber( track, message.start_group, message.start_object); QUICHE_DCHECK(start.has_value()); // Parser enforces this. std::optional end = session_->LocationToAbsoluteNumber( track, message.end_group, message.end_object); if (start < track.next_sequence() && track.visitor() != nullptr) { - SubscribeWindow window = end.has_value() - ? SubscribeWindow(start->group, start->object, - end->group, end->object) - : SubscribeWindow(start->group, start->object); + // TODO: Rework this. It's not good that the session notifies the + // application -- presumably triggering the send of a bunch of objects -- + // and only then sends the Subscribe OK. + SubscribeWindow window = + end.has_value() + ? SubscribeWindow(message.subscribe_id, start->group, start->object, + end->group, end->object) + : SubscribeWindow(message.subscribe_id, start->group, + start->object); std::optional past_objects_available = - track.visitor()->OnSubscribeRequestForPast(window); - if (!past_objects_available.has_value()) { - SendSubscribeError(message, kMoqtErrorObjectDoesntExist, - "Object does not exist"); + track.visitor()->OnSubscribeForPast(window); + if (past_objects_available.has_value()) { + SendSubscribeError(message, SubscribeErrorCode::kGenericError, + "Object does not exist", message.track_alias); return; } } MoqtSubscribeOk subscribe_ok; - subscribe_ok.track_namespace = message.track_namespace; - subscribe_ok.track_name = message.track_name; - subscribe_ok.track_id = track.track_alias(); + subscribe_ok.subscribe_id = message.subscribe_id; bool success = stream_->Write( session_->framer_.SerializeSubscribeOk(subscribe_ok).AsStringView()); if (!success) { - session_->Error("Failed to write SUBSCRIBE_OK message"); + session_->Error(MoqtError::kGenericError, + "Failed to write SUBSCRIBE_OK message"); return; } QUIC_DLOG(INFO) << ENDPOINT << "Created subscription for " << message.track_namespace << ":" << message.track_name; if (!end.has_value()) { - track.AddWindow(SubscribeWindow(start->group, start->object)); + track.AddWindow( + SubscribeWindow(message.subscribe_id, start->group, start->object)); return; } - track.AddWindow( - SubscribeWindow(start->group, start->object, end->group, end->object)); + track.AddWindow(SubscribeWindow(message.subscribe_id, start->group, + start->object, end->group, end->object)); } void MoqtSession::Stream::OnSubscribeOkMessage(const MoqtSubscribeOk& message) { if (!CheckIfIsControlStream()) { return; } - if (session_->tracks_by_alias_.contains(message.track_id)) { - session_->Error("Received duplicate track_alias"); + auto it = session_->active_subscribes_.find(message.subscribe_id); + if (it == session_->active_subscribes_.end()) { + session_->Error(MoqtError::kProtocolViolation, + "Received SUBSCRIBE_OK for nonexistent subscribe"); return; } - auto it = session_->remote_tracks_.find(FullTrackName( - std::string(message.track_namespace), std::string(message.track_name))); - if (it == session_->remote_tracks_.end()) { - session_->Error("Received SUBSCRIBE_OK for nonexistent subscribe"); - return; - } - // Note that if there are multiple SUBSCRIBE_OK for the same track, - // RemoteTrack.track_alias() will be the last alias received, but - // tracks_by_alias_ will have an entry for every track_alias received. - // TODO: revise this data structure to make it easier to clean up - // RemoteTracks, unless draft changes make it irrelevant. + MoqtSubscribe& subscribe = it->second.message; QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_OK for " - << message.track_namespace << ":" << message.track_name - << ", track_alias = " << message.track_id; - RemoteTrack& track = it->second; - track.set_track_alias(message.track_id); - session_->tracks_by_alias_[message.track_id] = &track; + << "subscribe_id = " << message.subscribe_id + << subscribe.track_namespace << ":" << subscribe.track_name; + // Copy the Remote Track from session_->active_subscribes_ to + // session_->remote_tracks_. + FullTrackName ftn(subscribe.track_namespace, subscribe.track_name); + RemoteTrack::Visitor* visitor = it->second.visitor; + session_->remote_tracks_.try_emplace(subscribe.track_alias, ftn, + subscribe.track_alias, visitor); // TODO: handle expires. - if (track.visitor() != nullptr) { - track.visitor()->OnReply(track.full_track_name(), std::nullopt); + if (visitor != nullptr) { + visitor->OnReply(ftn, std::nullopt); } - // Clear the buffer for this track alias. - auto it2 = session_->object_queue_.find(message.track_id); - if (it2 == session_->object_queue_.end() || track.visitor() == nullptr) { - // Nothing is buffered, or the app hasn't registered a visitor anyway. - return; - } - QUIC_DLOG(INFO) << ENDPOINT << "Processing buffered OBJECTs for track_alias " - << message.track_id; - std::vector& queue = it2->second; - for (BufferedObject& to_deliver : queue) { - track.visitor()->OnObjectFragment( - track.full_track_name(), to_deliver.stream_id, - to_deliver.message.group_sequence, to_deliver.message.object_sequence, - to_deliver.message.object_send_order, to_deliver.payload, - to_deliver.eom); - session_->num_buffered_objects_--; - } - session_->object_queue_.erase(it2); + session_->active_subscribes_.erase(it); } void MoqtSession::Stream::OnSubscribeErrorMessage( @@ -570,18 +619,34 @@ void MoqtSession::Stream::OnSubscribeErrorMessage( if (!CheckIfIsControlStream()) { return; } - auto it = session_->remote_tracks_.find(FullTrackName( - std::string(message.track_namespace), std::string(message.track_name))); - if (it == session_->remote_tracks_.end()) { - session_->Error("Received SUBSCRIBE_ERROR for nonexistent subscribe"); + auto it = session_->active_subscribes_.find(message.subscribe_id); + if (it == session_->active_subscribes_.end()) { + session_->Error(MoqtError::kProtocolViolation, + "Received SUBSCRIBE_ERROR for nonexistent subscribe"); return; } + MoqtSubscribe& subscribe = it->second.message; QUIC_DLOG(INFO) << ENDPOINT << "Received the SUBSCRIBE_ERROR for " - << message.track_namespace << ":" << message.track_name - << ", error = " << message.reason_phrase; - if (it->second.visitor() != nullptr) { - it->second.visitor()->OnReply(it->second.full_track_name(), - message.reason_phrase); + << "subscribe_id = " << message.subscribe_id << " (" + << subscribe.track_namespace << ":" << subscribe.track_name + << ")" << ", error = " << static_cast(message.error_code) + << " (" << message.reason_phrase << ")"; + RemoteTrack::Visitor* visitor = it->second.visitor; + FullTrackName ftn(subscribe.track_namespace, subscribe.track_name); + if (message.error_code == SubscribeErrorCode::kRetryTrackAlias) { + // Automatically resubscribe with new alias. + session_->remote_track_aliases_[ftn] = message.track_alias; + session_->Subscribe(subscribe, visitor); + } else if (visitor != nullptr) { + visitor->OnReply(ftn, message.reason_phrase); + } + session_->active_subscribes_.erase(it); +} + +void MoqtSession::Stream::OnUnsubscribeMessage(const MoqtUnsubscribe& message) { + // Search all the tracks to find the subscribe ID. + for (auto& [name, track] : session_->local_tracks_) { + track.DeleteWindow(message.subscribe_id); } } @@ -594,7 +659,8 @@ void MoqtSession::Stream::OnAnnounceMessage(const MoqtAnnounce& message) { bool success = stream_->Write(session_->framer_.SerializeAnnounceOk(ok).AsStringView()); if (!success) { - session_->Error("Failed to write ANNOUNCE_OK message"); + session_->Error(MoqtError::kGenericError, + "Failed to write ANNOUNCE_OK message"); return; } } @@ -605,7 +671,8 @@ void MoqtSession::Stream::OnAnnounceOkMessage(const MoqtAnnounceOk& message) { } auto it = session_->pending_outgoing_announces_.find(message.track_namespace); if (it == session_->pending_outgoing_announces_.end()) { - session_->Error("Received ANNOUNCE_OK for nonexistent announce"); + session_->Error(MoqtError::kProtocolViolation, + "Received ANNOUNCE_OK for nonexistent announce"); return; } std::move(it->second)(message.track_namespace, std::nullopt); @@ -619,24 +686,28 @@ void MoqtSession::Stream::OnAnnounceErrorMessage( } auto it = session_->pending_outgoing_announces_.find(message.track_namespace); if (it == session_->pending_outgoing_announces_.end()) { - session_->Error("Received ANNOUNCE_ERROR for nonexistent announce"); + session_->Error(MoqtError::kProtocolViolation, + "Received ANNOUNCE_ERROR for nonexistent announce"); return; } std::move(it->second)(message.track_namespace, message.reason_phrase); session_->pending_outgoing_announces_.erase(it); } -void MoqtSession::Stream::OnParsingError(absl::string_view reason) { - session_->Error(absl::StrCat("Parse error: ", reason)); +void MoqtSession::Stream::OnParsingError(MoqtError error_code, + absl::string_view reason) { + session_->Error(error_code, absl::StrCat("Parse error: ", reason)); } bool MoqtSession::Stream::CheckIfIsControlStream() { if (!is_control_stream_.has_value()) { - session_->Error("Received SUBSCRIBE_REQUEST as first message"); + session_->Error(MoqtError::kProtocolViolation, + "Received SUBSCRIBE_REQUEST as first message"); return false; } if (!*is_control_stream_) { - session_->Error("Received SUBSCRIBE_REQUEST on non-control stream"); + session_->Error(MoqtError::kProtocolViolation, + "Received SUBSCRIBE_REQUEST on non-control stream"); return false; } return true; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h index 645372b9d8..911849af99 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_session.h @@ -9,10 +9,9 @@ #include #include #include -#include #include "absl/container/flat_hash_map.h" -#include "absl/container/node_hash_map.h" +#include "absl/container/flat_hash_set.h" #include "absl/strings/string_view.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/moqt/moqt_framer.h" @@ -73,14 +72,14 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { void OnCanCreateNewOutgoingBidirectionalStream() override {} void OnCanCreateNewOutgoingUnidirectionalStream() override {} - void Error(absl::string_view error); + void Error(MoqtError code, absl::string_view error); quic::Perspective perspective() const { return parameters_.perspective; } // Add to the list of tracks that can be subscribed to. Call this before // Announce() so that subscriptions can be processed correctly. If |visitor| - // is nullptr, then incoming SUBSCRIBE_REQUEST for objects in the path will - // receive SUBSCRIBE_OK, but never actually get the objects. + // is nullptr, then incoming SUBSCRIBE for objects in the path will receive + // SUBSCRIBE_OK, but never actually get the objects. void AddLocalTrack(const FullTrackName& full_track_name, LocalTrack::Visitor* visitor); // Send an ANNOUNCE message for |track_namespace|, and call @@ -90,9 +89,9 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { MoqtAnnounceCallback announce_callback); bool HasSubscribers(const FullTrackName& full_track_name) const; - // Returns true if SUBSCRIBE_REQUEST was sent. If there is already a - // subscription to the track, the message will still be sent. However, the - // visitor will be ignored. + // Returns true if SUBSCRIBE was sent. If there is already a subscription to + // the track, the message will still be sent. However, the visitor will be + // ignored. bool SubscribeAbsolute(absl::string_view track_namespace, absl::string_view name, uint64_t start_group, uint64_t start_object, RemoteTrack::Visitor* visitor, @@ -111,15 +110,20 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { RemoteTrack::Visitor* visitor, absl::string_view auth_info = ""); - // Returns the stream ID if successful, nullopt if not. - // TODO: Add a callback if stream creation is delayed. - std::optional OpenUnidirectionalStream(); - // Will automatically assign a new sequence number. If |start_new_group|, - // increment group_sequence and set object_sequence to 0. Otherwise, - // increment object_sequence. - void PublishObjectToStream(webtransport::StreamId stream_id, - FullTrackName full_track_name, - bool start_new_group, absl::string_view payload); + // Returns false if it could not open a stream when necessary, or if the + // track does not exist (there was no call to AddLocalTrack). Will still + // return false is some streams succeed. + // Also returns false if |payload_length| exists but is shorter than + // |payload|. + // |payload.length() >= |payload_length|, because the application can deliver + // partial objects. + bool PublishObject(FullTrackName& full_track_name, uint64_t group_id, + uint64_t object_id, uint64_t object_send_order, + MoqtForwardingPreference forwarding_preference, + absl::string_view payload, + std::optional payload_length, + bool end_of_stream); + // TODO: Add an API to FIN the stream for a particular track/group/object. private: friend class test::MoqtSessionPeer; @@ -145,15 +149,15 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { void OnWriteSideInDataRecvdState() override {} // MoqtParserVisitor implementation. + // TODO: Handle a stream FIN. void OnObjectMessage(const MoqtObject& message, absl::string_view payload, bool end_of_message) override; void OnClientSetupMessage(const MoqtClientSetup& message) override; void OnServerSetupMessage(const MoqtServerSetup& message) override; - void OnSubscribeRequestMessage( - const MoqtSubscribeRequest& message) override; + void OnSubscribeMessage(const MoqtSubscribe& message) override; void OnSubscribeOkMessage(const MoqtSubscribeOk& message) override; void OnSubscribeErrorMessage(const MoqtSubscribeError& message) override; - void OnUnsubscribeMessage(const MoqtUnsubscribe& /*message*/) override {} + void OnUnsubscribeMessage(const MoqtUnsubscribe& message) override; void OnSubscribeFinMessage(const MoqtSubscribeFin& /*message*/) override {} void OnSubscribeRstMessage(const MoqtSubscribeRst& /*message*/) override {} void OnAnnounceMessage(const MoqtAnnounce& message) override; @@ -161,7 +165,8 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { void OnAnnounceErrorMessage(const MoqtAnnounceError& message) override; void OnUnannounceMessage(const MoqtUnannounce& /*message*/) override {} void OnGoAwayMessage(const MoqtGoAway& /*message*/) override {} - void OnParsingError(absl::string_view reason) override; + void OnParsingError(MoqtError error_code, + absl::string_view reason) override; quic::Perspective perspective() const { return session_->parameters_.perspective; @@ -171,9 +176,10 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { private: friend class test::MoqtSessionPeer; - void SendSubscribeError(const MoqtSubscribeRequest& message, - uint64_t error_code, - absl::string_view reason_phrase); + void SendSubscribeError(const MoqtSubscribe& message, + SubscribeErrorCode error_code, + absl::string_view reason_phrase, + uint64_t track_alias); bool CheckIfIsControlStream(); MoqtSession* session_; @@ -185,30 +191,16 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { std::string partial_object_; }; - // If parameters_.deliver_partial_objects is false, then the session buffers - // these objects until they arrive in their entirety. This stores the - // relevant information to later deliver this object via OnObject(). - struct BufferedObject { - uint32_t stream_id; - MoqtObject message; - std::string payload; - bool eom; - BufferedObject(uint32_t id, const MoqtObject& header, - absl::string_view body, bool end_of_message) - : stream_id(id), - message(header), - payload(std::string(body)), - eom(end_of_message) {} - }; - - // Returns false if the SUBSCRIBE_REQUEST isn't sent. - bool Subscribe(const MoqtSubscribeRequest& message, - RemoteTrack::Visitor* visitor); + // Returns false if the SUBSCRIBE isn't sent. + bool Subscribe(MoqtSubscribe& message, RemoteTrack::Visitor* visitor); // converts two MoqtLocations into absolute sequences. std::optional LocationToAbsoluteNumber( const LocalTrack& track, const std::optional& group, const std::optional& object); + // Returns the stream ID if successful, nullopt if not. + // TODO: Add a callback if stream creation is delayed. + std::optional OpenUnidirectionalStream(); webtransport::Session* session_; MoqtSessionParameters parameters_; @@ -220,18 +212,28 @@ class QUICHE_EXPORT MoqtSession : public webtransport::SessionVisitor { std::optional control_stream_; std::string error_; - // All the tracks the session is subscribed to. Multiple subscribes to the - // same track are recorded in a single subscription. - absl::node_hash_map remote_tracks_; + // All the tracks the session is subscribed to, indexed by track_alias. + // Multiple subscribes to the same track are recorded in a single + // subscription. + absl::flat_hash_map remote_tracks_; + // Look up aliases for remote tracks by name + absl::flat_hash_map remote_track_aliases_; + uint64_t next_remote_track_alias_ = 0; + // All the tracks the peer can subscribe to. absl::flat_hash_map local_tracks_; + // This is only used to check for track_alias collisions. + absl::flat_hash_set used_track_aliases_; + uint64_t next_local_track_alias_ = 0; - // Remote tracks indexed by TrackId. Must be active. - absl::flat_hash_map tracks_by_alias_; - uint64_t next_track_alias_ = 0; - // Buffer for OBJECTs that arrive with an unknown track alias. - absl::flat_hash_map> object_queue_; - int num_buffered_objects_ = 0; + // Indexed by subscribe_id. + struct ActiveSubscribe { + MoqtSubscribe message; + RemoteTrack::Visitor* visitor; + }; + // Outgoing SUBSCRIBEs that have not received SUBSCRIBE_OK or SUBSCRIBE_ERROR. + absl::flat_hash_map active_subscribes_; + uint64_t next_subscribe_id_ = 0; // Indexed by track namespace. absl::flat_hash_map diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc new file mode 100644 index 0000000000..9bea57025b --- /dev/null +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.cc @@ -0,0 +1,107 @@ +// Copyright 2024 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 "quiche/quic/moqt/moqt_subscribe_windows.h" + +#include +#include +#include + +#include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/web_transport/web_transport.h" + +namespace moqt { + +bool SubscribeWindow::InWindow(const FullSequence& seq) const { + if (seq < start_) { + return false; + } + return (!end_.has_value() || seq <= *end_); +} + +std::optional SubscribeWindow::GetStreamForSequence( + FullSequence sequence, + MoqtForwardingPreference forwarding_preference) const { + if (forwarding_preference == MoqtForwardingPreference::kTrack) { + return track_stream_; + } + auto group_it = group_streams_.find(sequence.group); + if (group_it == group_streams_.end()) { + return std::nullopt; + } + if (forwarding_preference == MoqtForwardingPreference::kGroup) { + return group_it->second.group_stream; + } + auto object_it = group_it->second.object_streams.find(sequence.object); + if (object_it == group_it->second.object_streams.end()) { + return std::nullopt; + } + return object_it->second; +} + +void SubscribeWindow::AddStream(MoqtForwardingPreference forwarding_preference, + uint64_t group_id, uint64_t object_id, + webtransport::StreamId stream_id) { + if (forwarding_preference == MoqtForwardingPreference::kTrack) { + QUIC_BUG_IF(quic_bug_moqt_draft_02_01, track_stream_.has_value()) + << "Track stream already assigned"; + track_stream_ = stream_id; + return; + } + if (forwarding_preference == MoqtForwardingPreference::kGroup) { + QUIC_BUG_IF(quic_bug_moqt_draft_02_02, + group_streams_[group_id].group_stream.has_value()) + << "Group stream already assigned"; + group_streams_[group_id].group_stream = stream_id; + return; + } + // ObjectStream or ObjectPreferDatagram + QUIC_BUG_IF(quic_bug_moqt_draft_02_03, + group_streams_[group_id].object_streams.contains(object_id)) + << "Object stream already assigned"; + group_streams_[group_id].object_streams[object_id] = stream_id; +} + +void SubscribeWindow::RemoveStream( + MoqtForwardingPreference forwarding_preference, uint64_t group_id, + uint64_t object_id) { + if (forwarding_preference == moqt::MoqtForwardingPreference::kTrack) { + track_stream_ = std::nullopt; + return; + } + auto group_it = group_streams_.find(group_id); + if (group_it == group_streams_.end()) { + return; + } + GroupStreams& group = group_it->second; + if (forwarding_preference == moqt::MoqtForwardingPreference::kGroup) { + group.group_stream = std::nullopt; + if (group.object_streams.empty()) { + group_streams_.erase(group_id); + } + return; + } + // ObjectStream or ObjectPreferDatagram + if (group.object_streams.contains(object_id)) { + group_streams_[group_id].object_streams.erase(object_id); + if (!group.group_stream.has_value() && + group_streams_[group_id].object_streams.empty()) { + group_streams_.erase(group_id); + } + } +} + +std::vector MoqtSubscribeWindows::SequenceIsSubscribed( + FullSequence sequence) { + std::vector retval; + for (auto& [subscribe_id, window] : windows_) { + if (window.InWindow(sequence)) { + retval.push_back(&(window)); + } + } + return retval; +} + +} // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h index 4bf5f76208..e6ec05d28f 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_subscribe_windows.h @@ -6,62 +6,94 @@ #define QUICHE_QUIC_MOQT_SUBSCRIBE_WINDOWS_H #include -#include #include +#include +#include "absl/container/node_hash_map.h" #include "quiche/quic/moqt/moqt_messages.h" +#include "quiche/common/platform/api/quiche_export.h" +#include "quiche/web_transport/web_transport.h" namespace moqt { -struct SubscribeWindow { - FullSequence start; - std::optional end; +// Classes to track subscriptions to local tracks: the sequence numbers +// subscribed, the streams involved, and the subscribe IDs. +class QUICHE_EXPORT SubscribeWindow { + public: // Creates a half-open window. - SubscribeWindow(uint64_t start_group, uint64_t start_object) { - start = {start_group, start_object}; - end = std::nullopt; - } + SubscribeWindow(uint64_t subscribe_id, uint64_t start_group, + uint64_t start_object) + : subscribe_id_(subscribe_id), start_({start_group, start_object}) {} + // Creates a closed window. - SubscribeWindow(uint64_t start_group, uint64_t start_object, - uint64_t end_group, uint64_t end_object) { - start = {start_group, start_object}; - end = {end_group, end_object}; - } - bool InWindow(const FullSequence& seq) const { - if (seq < start) { - return false; - } - if (!end.has_value() || seq < *end) { - return true; - } - return false; - } + SubscribeWindow(uint64_t subscribe_id, uint64_t start_group, + uint64_t start_object, uint64_t end_group, + uint64_t end_object) + : subscribe_id_(subscribe_id), + start_({start_group, start_object}), + end_(FullSequence(end_group, end_object)) {} + + uint64_t subscribe_id() const { return subscribe_id_; } + + bool InWindow(const FullSequence& seq) const; + + // Returns the stream to send |sequence| on, if already opened. + std::optional GetStreamForSequence( + FullSequence sequence, + MoqtForwardingPreference forwarding_preference) const; + + // Records what stream is being used for a track, group, or object depending + // on |forwarding_preference|. Triggers QUIC_BUG if already assigned. + void AddStream(MoqtForwardingPreference forwarding_preference, + uint64_t group_id, uint64_t object_id, + webtransport::StreamId stream_id); + + void RemoveStream(MoqtForwardingPreference forwarding_preference, + uint64_t group_id, uint64_t object_id); + + private: + struct GroupStreams { + std::optional group_stream; + absl::flat_hash_map object_streams; + }; + const uint64_t subscribe_id_; + const FullSequence start_; + const std::optional end_ = std::nullopt; + // Open streams for this subscription + std::optional track_stream_; + absl::flat_hash_map group_streams_; }; // Class to keep track of the sequence number blocks to which a peer is // subscribed. -class MoqtSubscribeWindows { +class QUICHE_EXPORT MoqtSubscribeWindows { public: MoqtSubscribeWindows() {} - bool SequenceIsSubscribed(uint64_t group, uint64_t object) const { - FullSequence seq(group, object); - for (auto it : windows) { - if (it.InWindow(seq)) { - return true; - } - } - return false; - } + // Returns a vector of subscribe IDs that apply to the object. They will be in + // reverse order of the AddWindow calls. + std::vector SequenceIsSubscribed(FullSequence sequence); // |window| has already been converted into absolute sequence numbers. An // optimization could consolidate overlapping subscribe windows. - void AddWindow(SubscribeWindow window) { windows.push_front(window); } + void AddWindow(SubscribeWindow window) { + windows_.emplace(window.subscribe_id(), window); + } + void RemoveWindow(uint64_t subscribe_id) { windows_.erase(subscribe_id); } - bool IsEmpty() const { return windows.empty(); } + bool IsEmpty() const { return windows_.empty(); } + + SubscribeWindow* GetWindow(uint64_t subscribe_id) { + auto it = windows_.find(subscribe_id); + if (it == windows_.end()) { + return nullptr; + } + return &it->second; + } private: - std::list windows; + // Indexed by Subscribe ID. + absl::node_hash_map windows_; }; } // namespace moqt diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h index 4dad086ea8..e52b084cb1 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/moqt_track.h @@ -7,6 +7,7 @@ #include #include +#include #include "absl/strings/string_view.h" #include "quiche/quic/moqt/moqt_messages.h" @@ -27,51 +28,65 @@ class LocalTrack { // the session will send SUBSCRIBE_OK. If the return has a value, the value // is the error message (the session will send SUBSCRIBE_ERROR). Via this // API, the application decides if a partially fulfillable - // SUBSCRIBE_REQUEST results in an error or not. - virtual std::optional OnSubscribeRequestForPast( + // SUBSCRIBE results in an error or not. + virtual std::optional OnSubscribeForPast( const SubscribeWindow& window) = 0; }; // |visitor| must not be nullptr. - LocalTrack(const FullTrackName& full_track_name, uint64_t track_alias, - Visitor* visitor) - : full_track_name_(full_track_name), - track_alias_(track_alias), - visitor_(visitor) {} + LocalTrack(const FullTrackName& full_track_name, Visitor* visitor) + : full_track_name_(full_track_name), visitor_(visitor) {} // Creates a LocalTrack that does not start at sequence (0,0) - LocalTrack(const FullTrackName& full_track_name, uint64_t track_alias, - Visitor* visitor, FullSequence next_sequence) + LocalTrack(const FullTrackName& full_track_name, Visitor* visitor, + FullSequence next_sequence) : full_track_name_(full_track_name), - track_alias_(track_alias), next_sequence_(next_sequence), visitor_(visitor) {} const FullTrackName& full_track_name() const { return full_track_name_; } - uint64_t track_alias() const { return track_alias_; } + std::optional track_alias() const { return track_alias_; } + void set_track_alias(uint64_t track_alias) { track_alias_ = track_alias; } Visitor* visitor() { return visitor_; } - bool ShouldSend(uint64_t group, uint64_t object) const { - return windows_.SequenceIsSubscribed(group, object); + // Returns the subscribe windows that want the object defined by (|group|, + // |object|). + std::vector ShouldSend(FullSequence sequence) { + return windows_.SequenceIsSubscribed(sequence); } void AddWindow(SubscribeWindow window) { windows_.AddWindow(window); } + void DeleteWindow(uint64_t subscribe_id) { + windows_.RemoveWindow(subscribe_id); + } // Returns the largest observed sequence, but increments the object sequence // by one. const FullSequence& next_sequence() const { return next_sequence_; } - FullSequence& next_sequence_mutable() { return next_sequence_; } + // Updates next_sequence_ if |sequence| is larger. + void SentSequence(FullSequence sequence) { + if (next_sequence_ <= sequence) { + next_sequence_ = {sequence.group, sequence.object + 1}; + } + } bool HasSubscriber() const { return !windows_.IsEmpty(); } + SubscribeWindow* GetWindow(uint64_t subscribe_id) { + return windows_.GetWindow(subscribe_id); + } + private: // This only needs to track subscriptions to current and future objects; // requests for objects in the past are forwarded to the application. const FullTrackName full_track_name_; - const uint64_t track_alias_; + // Let the first SUBSCRIBE determine the track alias. + std::optional track_alias_; // The sequence numbers from this track to which the peer is subscribed. MoqtSubscribeWindows windows_; + // By recording the highest observed sequence number, MoQT can interpret + // relative sequence numbers in SUBSCRIBEs. FullSequence next_sequence_ = {0, 0}; Visitor* visitor_; }; @@ -82,34 +97,36 @@ class RemoteTrack { class Visitor { public: virtual ~Visitor() = default; - // Called when the session receives a response to the SUBSCRIBE_REQUEST. + // Called when the session receives a response to the SUBSCRIBE, unless it's + // a SUBSCRIBE_ERROR with a new track_alias. In that case, the session will + // automatically retry. virtual void OnReply( const FullTrackName& full_track_name, std::optional error_reason_phrase) = 0; - virtual void OnObjectFragment(const FullTrackName& full_track_name, - uint32_t stream_id, uint64_t group_sequence, - uint64_t object_sequence, - uint64_t object_send_order, - absl::string_view object, - bool end_of_message) = 0; + virtual void OnObjectFragment( + const FullTrackName& full_track_name, uint64_t group_sequence, + uint64_t object_sequence, uint64_t object_send_order, + MoqtForwardingPreference forwarding_preference, + absl::string_view object, bool end_of_message) = 0; // TODO(martinduke): Add final sequence numbers }; - RemoteTrack(const FullTrackName& full_track_name, Visitor* visitor) - : full_track_name_(full_track_name), visitor_(visitor) {} + RemoteTrack(const FullTrackName& full_track_name, uint64_t track_alias, + Visitor* visitor) + : full_track_name_(full_track_name), + track_alias_(track_alias), + visitor_(visitor) {} const FullTrackName& full_track_name() { return full_track_name_; } - std::optional track_alias() const { return track_alias_; } + uint64_t track_alias() const { return track_alias_; } Visitor* visitor() { return visitor_; } - void set_track_alias(uint64_t track_alias) { track_alias_ = track_alias; } - private: // TODO: There is no accounting for the number of outstanding subscribes, // because we can't match track names to individual subscribes. - FullTrackName full_track_name_; - std::optional track_alias_; + const FullTrackName full_track_name_; + const uint64_t track_alias_; Visitor* visitor_; }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h index ada4dea3a5..cd3d0948b0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/test_tools/moqt_test_message.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -34,10 +35,10 @@ class QUICHE_NO_EXPORT TestMessageBase { MoqtMessageType message_type() const { return message_type_; } typedef absl::variant + MoqtSubscribe, MoqtSubscribeOk, MoqtSubscribeError, + MoqtUnsubscribe, MoqtSubscribeFin, MoqtSubscribeRst, + MoqtAnnounce, MoqtAnnounceOk, MoqtAnnounceError, + MoqtUnannounce, MoqtGoAway> MessageStructuredData; // The total actual size of the message. @@ -112,19 +113,25 @@ class QUICHE_NO_EXPORT TestMessageBase { // Base class for the two subtypes of Object Message. class QUICHE_NO_EXPORT ObjectMessage : public TestMessageBase { public: - ObjectMessage(MoqtMessageType type) : TestMessageBase(type) {} + ObjectMessage(MoqtMessageType type) : TestMessageBase(type) { + object_.forwarding_preference = GetForwardingPreference(type); + } bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_id != object_.track_id) { + if (cast.subscribe_id != object_.subscribe_id) { QUIC_LOG(INFO) << "OBJECT Track ID mismatch"; return false; } - if (cast.group_sequence != object_.group_sequence) { + if (cast.track_alias != object_.track_alias) { + QUIC_LOG(INFO) << "OBJECT Track ID mismatch"; + return false; + } + if (cast.group_id != object_.group_id) { QUIC_LOG(INFO) << "OBJECT Group Sequence mismatch"; return false; } - if (cast.object_sequence != object_.object_sequence) { + if (cast.object_id != object_.object_id) { QUIC_LOG(INFO) << "OBJECT Object Sequence mismatch"; return false; } @@ -132,88 +139,155 @@ class QUICHE_NO_EXPORT ObjectMessage : public TestMessageBase { QUIC_LOG(INFO) << "OBJECT Object Send Order mismatch"; return false; } + if (cast.forwarding_preference != object_.forwarding_preference) { + QUIC_LOG(INFO) << "OBJECT Object Send Order mismatch"; + return false; + } + if (cast.payload_length != object_.payload_length) { + QUIC_LOG(INFO) << "OBJECT Payload Length mismatch"; + return false; + } return true; } - void ExpandVarints() override { - ExpandVarintsImpl("vvvvvv"); // first six fields are varints - } - MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(object_); } protected: MoqtObject object_ = { - /*track_id=*/4, - /*group_sequence=*/5, - /*object_sequence=*/6, + /*subscribe_id=*/3, + /*track_alias=*/4, + /*group_id*/ 5, + /*object_id=*/6, /*object_send_order=*/7, + /*forwarding_preference=*/MoqtForwardingPreference::kTrack, /*payload_length=*/std::nullopt, }; }; -class QUICHE_NO_EXPORT ObjectMessageWithLength : public ObjectMessage { +class QUICHE_NO_EXPORT ObjectStreamMessage : public ObjectMessage { public: - ObjectMessageWithLength() - : ObjectMessage(MoqtMessageType::kObjectWithPayloadLength) { + ObjectStreamMessage() : ObjectMessage(MoqtMessageType::kObjectStream) { SetWireImage(raw_packet_, sizeof(raw_packet_)); - object_.payload_length = payload_length_; - } - - bool EqualFieldValues(MessageStructuredData& values) const override { - auto cast = std::get(values); - if (cast.payload_length != payload_length_) { - QUIC_LOG(INFO) << "OBJECT Payload Length mismatch"; - return false; - } - return ObjectMessage::EqualFieldValues(values); + object_.forwarding_preference = MoqtForwardingPreference::kObject; } void ExpandVarints() override { ExpandVarintsImpl("vvvvvv"); // first six fields are varints } - MessageStructuredData structured_data() const override { - return TestMessageBase::MessageStructuredData(object_); + private: + uint8_t raw_packet_[9] = { + 0x00, 0x03, 0x04, 0x05, 0x06, 0x07, // varints + 0x66, 0x6f, 0x6f, // payload = "foo" + }; +}; + +class QUICHE_NO_EXPORT ObjectPreferDatagramMessage : public ObjectMessage { + public: + ObjectPreferDatagramMessage() + : ObjectMessage(MoqtMessageType::kObjectPreferDatagram) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + object_.forwarding_preference = MoqtForwardingPreference::kDatagram; + } + + void ExpandVarints() override { + ExpandVarintsImpl("vvvvvv"); // first six fields are varints } private: uint8_t raw_packet_[9] = { - 0x00, 0x04, 0x05, 0x06, 0x07, // varints - 0x03, 0x66, 0x6f, 0x6f, // payload = "foo" + 0x01, 0x03, 0x04, 0x05, 0x06, 0x07, // varints + 0x66, 0x6f, 0x6f, // payload = "foo" }; - std::optional payload_length_ = 3; }; -class QUICHE_NO_EXPORT ObjectMessageWithoutLength : public ObjectMessage { +// Concatentation of the base header and the object-specific header. Follow-on +// object headers are handled in a different class. +class QUICHE_NO_EXPORT StreamHeaderTrackMessage : public ObjectMessage { public: - ObjectMessageWithoutLength() - : ObjectMessage(MoqtMessageType::kObjectWithoutPayloadLength) { + StreamHeaderTrackMessage() + : ObjectMessage(MoqtMessageType::kStreamHeaderTrack) { SetWireImage(raw_packet_, sizeof(raw_packet_)); - } - - bool EqualFieldValues(MessageStructuredData& values) const override { - auto cast = std::get(values); - if (cast.payload_length != std::nullopt) { - QUIC_LOG(INFO) << "OBJECT Payload Length mismatch"; - return false; - } - return ObjectMessage::EqualFieldValues(values); + object_.forwarding_preference = MoqtForwardingPreference::kTrack; + object_.payload_length = 3; } void ExpandVarints() override { - ExpandVarintsImpl("vvvvv"); // first six fields are varints - } - - MessageStructuredData structured_data() const override { - return TestMessageBase::MessageStructuredData(object_); + ExpandVarintsImpl("--vvvvvv"); // six one-byte varints } private: - uint8_t raw_packet_[8] = { - 0x02, 0x04, 0x05, 0x06, 0x07, // varints - 0x66, 0x6f, 0x6f, // payload = "foo" + // Some tests check that a FIN sent at the halfway point of a message results + // in an error. Without the unnecessary expanded varint 0x0405, the halfway + // point falls at the end of the Stream Header, which is legal. Expand the + // varint so that the FIN would be illegal. + uint8_t raw_packet_[11] = { + 0x40, 0x50, // two byte type field + 0x03, 0x04, 0x07, // varints + 0x05, 0x06, // object middler + 0x03, 0x66, 0x6f, 0x6f, // payload = "foo" + }; +}; + +// Used only for tests that process multiple objects on one stream. +class QUICHE_NO_EXPORT StreamMiddlerTrackMessage : public ObjectMessage { + public: + StreamMiddlerTrackMessage() + : ObjectMessage(MoqtMessageType::kStreamHeaderTrack) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + object_.forwarding_preference = MoqtForwardingPreference::kTrack; + object_.payload_length = 3; + object_.group_id = 9; + object_.object_id = 10; + } + + void ExpandVarints() override { ExpandVarintsImpl("vvv"); } + + private: + uint8_t raw_packet_[6] = { + 0x09, 0x0a, 0x03, 0x62, 0x61, 0x72, // object middler; payload = "bar" + }; +}; + +class QUICHE_NO_EXPORT StreamHeaderGroupMessage : public ObjectMessage { + public: + StreamHeaderGroupMessage() + : ObjectMessage(MoqtMessageType::kStreamHeaderGroup) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + object_.forwarding_preference = MoqtForwardingPreference::kGroup; + object_.payload_length = 3; + } + + void ExpandVarints() override { + ExpandVarintsImpl("--vvvvvv"); // six one-byte varints + } + + private: + uint8_t raw_packet_[11] = { + 0x40, 0x51, // two-byte type field + 0x03, 0x04, 0x05, 0x07, // varints + 0x06, 0x03, 0x66, 0x6f, 0x6f, // object middler; payload = "foo" + }; +}; + +// Used only for tests that process multiple objects on one stream. +class QUICHE_NO_EXPORT StreamMiddlerGroupMessage : public ObjectMessage { + public: + StreamMiddlerGroupMessage() + : ObjectMessage(MoqtMessageType::kStreamHeaderGroup) { + SetWireImage(raw_packet_, sizeof(raw_packet_)); + object_.forwarding_preference = MoqtForwardingPreference::kGroup; + object_.payload_length = 3; + object_.object_id = 9; + } + + void ExpandVarints() override { ExpandVarintsImpl("vvv"); } + + private: + uint8_t raw_packet_[5] = { + 0x09, 0x03, 0x62, 0x61, 0x72, // object middler; payload = "bar" }; }; @@ -325,65 +399,94 @@ class QUICHE_NO_EXPORT ServerSetupMessage : public TestMessageBase { }; }; -class QUICHE_NO_EXPORT SubscribeRequestMessage : public TestMessageBase { +class QUICHE_NO_EXPORT SubscribeMessage : public TestMessageBase { public: - SubscribeRequestMessage() - : TestMessageBase(MoqtMessageType::kSubscribeRequest) { + SubscribeMessage() : TestMessageBase(MoqtMessageType::kSubscribe) { SetWireImage(raw_packet_, sizeof(raw_packet_)); } bool EqualFieldValues(MessageStructuredData& values) const override { - auto cast = std::get(values); - if (cast.track_namespace != subscribe_request_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST track namespace mismatch"; + auto cast = std::get(values); + if (cast.subscribe_id != subscribe_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE subscribe ID mismatch"; return false; } - if (cast.track_name != subscribe_request_.track_name) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST track name mismatch"; + if (cast.track_alias != subscribe_.track_alias) { + QUIC_LOG(INFO) << "SUBSCRIBE track alias mismatch"; return false; } - if (cast.start_group != subscribe_request_.start_group) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST start group mismatch"; + if (cast.track_namespace != subscribe_.track_namespace) { + QUIC_LOG(INFO) << "SUBSCRIBE track namespace mismatch"; return false; } - if (cast.start_object != subscribe_request_.start_object) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST start object mismatch"; + if (cast.track_name != subscribe_.track_name) { + QUIC_LOG(INFO) << "SUBSCRIBE track name mismatch"; return false; } - if (cast.end_group != subscribe_request_.end_group) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST end group mismatch"; + if (cast.start_group != subscribe_.start_group) { + QUIC_LOG(INFO) << "SUBSCRIBE start group mismatch"; return false; } - if (cast.end_object != subscribe_request_.end_object) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST end object mismatch"; + if (cast.start_object != subscribe_.start_object) { + QUIC_LOG(INFO) << "SUBSCRIBE start object mismatch"; return false; } - if (cast.authorization_info != subscribe_request_.authorization_info) { - QUIC_LOG(INFO) << "SUBSCRIBE REQUEST authorization info mismatch"; + if (cast.end_group != subscribe_.end_group) { + QUIC_LOG(INFO) << "SUBSCRIBE end group mismatch"; + return false; + } + if (cast.end_object != subscribe_.end_object) { + QUIC_LOG(INFO) << "SUBSCRIBE end object mismatch"; + return false; + } + if (cast.authorization_info != subscribe_.authorization_info) { + QUIC_LOG(INFO) << "SUBSCRIBE authorization info mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v----vvvvvvvvv---"); } + void ExpandVarints() override { + ExpandVarintsImpl("vvvv---v----vvvvvvvvv"); + } MessageStructuredData structured_data() const override { - return TestMessageBase::MessageStructuredData(subscribe_request_); + return TestMessageBase::MessageStructuredData(subscribe_); } private: - uint8_t raw_packet_[22] = { - 0x03, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x04, 0x61, 0x62, 0x63, 0x64, // track_name = "abcd" - 0x02, 0x04, // start_group = 4 (relative previous) - 0x01, 0x01, // start_object = 1 (absolute) - 0x00, // end_group = none - 0x00, // end_object = none - 0x01, // 1 parameter - 0x02, 0x03, 0x62, 0x61, 0x72, // authorization_info = "bar" + uint8_t raw_packet_[24] = { + 0x03, + 0x01, + 0x02, // id and alias + 0x03, + 0x66, + 0x6f, + 0x6f, // track_namespace = "foo" + 0x04, + 0x61, + 0x62, + 0x63, + 0x64, // track_name = "abcd" + 0x02, + 0x04, // start_group = 4 (relative previous) + 0x01, + 0x01, // start_object = 1 (absolute) + 0x00, // end_group = none + 0x00, // end_object = none + // TODO(martinduke): figure out what to do about the missing num + // parameters field. + 0x01, // 1 parameter + 0x02, + 0x03, + 0x62, + 0x61, + 0x72, // authorization_info = "bar" }; - MoqtSubscribeRequest subscribe_request_ = { + MoqtSubscribe subscribe_ = { + /*subscribe_id=*/1, + /*track_alias=*/2, /*track_namespace=*/"foo", /*track_name=*/"abcd", /*start_group=*/MoqtSubscribeLocation(false, (int64_t)(-4)), @@ -402,16 +505,8 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_ok_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE OK track namespace mismatch"; - return false; - } - if (cast.track_name != subscribe_ok_.track_name) { - QUIC_LOG(INFO) << "SUBSCRIBE OK track name mismatch"; - return false; - } - if (cast.track_id != subscribe_ok_.track_id) { - QUIC_LOG(INFO) << "SUBSCRIBE OK track ID mismatch"; + if (cast.subscribe_id != subscribe_ok_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE OK subscribe ID mismatch"; return false; } if (cast.expires != subscribe_ok_.expires) { @@ -421,25 +516,20 @@ class QUICHE_NO_EXPORT SubscribeOkMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v---vv"); } + void ExpandVarints() override { ExpandVarintsImpl("vvv"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_ok_); } private: - uint8_t raw_packet_[11] = { - 0x04, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x03, 0x62, 0x61, 0x72, // track_namespace = "bar" - 0x01, // track_id = 1 - 0x02, // expires = 2 + uint8_t raw_packet_[3] = { + 0x04, 0x01, 0x03, // subscribe_id = 1, expires = 3 }; MoqtSubscribeOk subscribe_ok_ = { - /*track_namespace=*/"foo", - /*track_name=*/"bar", - /*track_id=*/1, - /*expires=*/quic::QuicTimeDelta::FromMilliseconds(2), + /*subscribe_id=*/1, + /*expires=*/quic::QuicTimeDelta::FromMilliseconds(3), }; }; @@ -451,12 +541,8 @@ class QUICHE_NO_EXPORT SubscribeErrorMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_error_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE ERROR track namespace mismatch"; - return false; - } - if (cast.track_name != subscribe_error_.track_name) { - QUIC_LOG(INFO) << "SUBSCRIBE ERROR track name mismatch"; + if (cast.subscribe_id != subscribe_error_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE ERROR subscribe_id mismatch"; return false; } if (cast.error_code != subscribe_error_.error_code) { @@ -467,28 +553,32 @@ class QUICHE_NO_EXPORT SubscribeErrorMessage : public TestMessageBase { QUIC_LOG(INFO) << "SUBSCRIBE ERROR reason phrase mismatch"; return false; } + if (cast.track_alias != subscribe_error_.track_alias) { + QUIC_LOG(INFO) << "SUBSCRIBE ERROR track alias mismatch"; + return false; + } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v---vv---"); } + void ExpandVarints() override { ExpandVarintsImpl("vvvv---v"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_error_); } private: - uint8_t raw_packet_[14] = { - 0x05, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x03, 0x62, 0x61, 0x72, // track_namespace = "bar" - 0x01, // error_code = 1 - 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" + uint8_t raw_packet_[8] = { + 0x05, 0x02, // subscribe_id = 2 + 0x01, // error_code = 2 + 0x03, 0x62, 0x61, 0x72, // reason_phrase = "bar" + 0x04, // track_alias = 4 }; MoqtSubscribeError subscribe_error_ = { - /*track_namespace=*/"foo", - /*track_name=*/"bar", - /*subscribe=*/1, + /*subscribe_id=*/2, + /*subscribe=*/SubscribeErrorCode::kInvalidRange, /*reason_phrase=*/"bar", + /*track_alias=*/4, }; }; @@ -500,32 +590,26 @@ class QUICHE_NO_EXPORT UnsubscribeMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != unsubscribe_.track_namespace) { - QUIC_LOG(INFO) << "UNSUBSCRIBE track name mismatch"; - return false; - } - if (cast.track_name != unsubscribe_.track_name) { - QUIC_LOG(INFO) << "UNSUBSCRIBE track name mismatch"; + if (cast.subscribe_id != unsubscribe_.subscribe_id) { + QUIC_LOG(INFO) << "UNSUBSCRIBE subscribe ID mismatch"; return false; } return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v---"); } + void ExpandVarints() override { ExpandVarintsImpl("vv"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(unsubscribe_); } private: - uint8_t raw_packet_[9] = { - 0x0a, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x03, 0x62, 0x61, 0x72, // track_namespace = "bar" + uint8_t raw_packet_[2] = { + 0x0a, 0x03, // subscribe_id = 3 }; MoqtUnsubscribe unsubscribe_ = { - /*track_namespace=*/"foo", - /*track_name=*/"bar", + /*subscribe_id=*/3, }; }; @@ -537,12 +621,8 @@ class QUICHE_NO_EXPORT SubscribeFinMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_fin_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE_FIN track name mismatch"; - return false; - } - if (cast.track_name != subscribe_fin_.track_name) { - QUIC_LOG(INFO) << "SUBSCRIBE_FIN track name mismatch"; + if (cast.subscribe_id != subscribe_fin_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_FIN subscribe ID mismatch"; return false; } if (cast.final_group != subscribe_fin_.final_group) { @@ -556,23 +636,21 @@ class QUICHE_NO_EXPORT SubscribeFinMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v---vv"); } + void ExpandVarints() override { ExpandVarintsImpl("vvvv"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_fin_); } private: - uint8_t raw_packet_[11] = { - 0x0b, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x03, 0x62, 0x61, 0x72, // track_namespace = "bar" - 0x08, // final_group = 8 - 0x0c, // final_object = 12 + uint8_t raw_packet_[4] = { + 0x0b, 0x03, // subscribe_id = 3 + 0x08, // final_group = 8 + 0x0c, // final_object = 12 }; MoqtSubscribeFin subscribe_fin_ = { - /*track_namespace=*/"foo", - /*track_name=*/"bar", + /*subscribe_id=*/3, /*final_group=*/8, /*final_object=*/12, }; @@ -586,12 +664,8 @@ class QUICHE_NO_EXPORT SubscribeRstMessage : public TestMessageBase { bool EqualFieldValues(MessageStructuredData& values) const override { auto cast = std::get(values); - if (cast.track_namespace != subscribe_rst_.track_namespace) { - QUIC_LOG(INFO) << "SUBSCRIBE_RST track name mismatch"; - return false; - } - if (cast.track_name != subscribe_rst_.track_name) { - QUIC_LOG(INFO) << "SUBSCRIBE_RST track name mismatch"; + if (cast.subscribe_id != subscribe_rst_.subscribe_id) { + QUIC_LOG(INFO) << "SUBSCRIBE_RST subscribe ID mismatch"; return false; } if (cast.error_code != subscribe_rst_.error_code) { @@ -613,25 +687,23 @@ class QUICHE_NO_EXPORT SubscribeRstMessage : public TestMessageBase { return true; } - void ExpandVarints() override { ExpandVarintsImpl("vv---v---vv--vv"); } + void ExpandVarints() override { ExpandVarintsImpl("vvvv--vv"); } MessageStructuredData structured_data() const override { return TestMessageBase::MessageStructuredData(subscribe_rst_); } private: - uint8_t raw_packet_[15] = { - 0x0c, 0x03, 0x66, 0x6f, 0x6f, // track_namespace = "foo" - 0x03, 0x62, 0x61, 0x72, // track_namespace = "bar" - 0x03, // error_code = 3 - 0x02, 0x68, 0x69, // reason_phrase = "hi" - 0x08, // final_group = 8 - 0x0c, // final_object = 12 + uint8_t raw_packet_[8] = { + 0x0c, 0x02, // subscribe_id = 2 + 0x03, // error_code = 3 + 0x02, 0x68, 0x69, // reason_phrase = "hi" + 0x08, // final_group = 8 + 0x0c, // final_object = 12 }; MoqtSubscribeRst subscribe_rst_ = { - /*track_namespace=*/"foo", - /*track_name=*/"bar", + /*subscribe_id=*/2, /*error_code=*/3, /*reason_phrase=*/"hi", /*final_group=*/8, @@ -813,6 +885,49 @@ class QUICHE_NO_EXPORT GoAwayMessage : public TestMessageBase { }; }; +// Factory function for test messages. +static inline std::unique_ptr CreateTestMessage( + MoqtMessageType message_type, bool is_webtrans) { + switch (message_type) { + case MoqtMessageType::kObjectStream: + return std::make_unique(); + case MoqtMessageType::kObjectPreferDatagram: + return std::make_unique(); + case MoqtMessageType::kSubscribe: + return std::make_unique(); + case MoqtMessageType::kSubscribeOk: + return std::make_unique(); + case MoqtMessageType::kSubscribeError: + return std::make_unique(); + case MoqtMessageType::kUnsubscribe: + return std::make_unique(); + case MoqtMessageType::kSubscribeFin: + return std::make_unique(); + case MoqtMessageType::kSubscribeRst: + return std::make_unique(); + case MoqtMessageType::kAnnounce: + return std::make_unique(); + case MoqtMessageType::kAnnounceOk: + return std::make_unique(); + case MoqtMessageType::kAnnounceError: + return std::make_unique(); + case MoqtMessageType::kUnannounce: + return std::make_unique(); + case MoqtMessageType::kGoAway: + return std::make_unique(); + case MoqtMessageType::kClientSetup: + return std::make_unique(is_webtrans); + case MoqtMessageType::kServerSetup: + return std::make_unique(); + case MoqtMessageType::kStreamHeaderTrack: + return std::make_unique(); + case MoqtMessageType::kStreamHeaderGroup: + return std::make_unique(); + default: + return nullptr; + } +} + } // namespace moqt::test #endif // QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_TEST_MESSAGE_H_ diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc index 536709c89a..c5cb07049e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/chat_client_bin.cc @@ -107,12 +107,11 @@ class ChatClient { } } - void OnObjectFragment(const moqt::FullTrackName& full_track_name, - uint32_t /*stream_id*/, uint64_t group_sequence, - uint64_t object_sequence, - uint64_t /*object_send_order*/, - absl::string_view object, - bool end_of_message) override { + void OnObjectFragment( + const moqt::FullTrackName& full_track_name, uint64_t group_sequence, + uint64_t object_sequence, uint64_t /*object_send_order*/, + moqt::MoqtForwardingPreference /*forwarding_preference*/, + absl::string_view object, bool end_of_message) override { if (!end_of_message) { std::cerr << "Error: received partial message despite requesting " "buffering\n"; @@ -147,7 +146,8 @@ class ChatClient { std::optional message) { if (message.has_value()) { std::cout << "ANNOUNCE rejected, " << *message << "\n"; - session_->Error("Local ANNOUNCE rejected"); + session_->Error(moqt::MoqtError::kGenericError, + "Local ANNOUNCE rejected"); return; } std::cout << "ANNOUNCE for " << track_namespace << " accepted\n"; @@ -224,7 +224,8 @@ class ChatClient { if (!got_version) { // Chat server currently does not send version if (line != "version=1") { - session_->Error("Catalog does not begin with version"); + session_->Error(moqt::MoqtError::kProtocolViolation, + "Catalog does not begin with version"); return; } got_version = true; @@ -277,7 +278,8 @@ class ChatClient { subscribes_to_make_++; } else { if (it->second.from_group == group_sequence) { - session_->Error("User listed twice in Catalog"); + session_->Error(moqt::MoqtError::kProtocolViolation, + "User listed twice in Catalog"); return; } it->second.from_group = group_sequence; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc index 07c088e4f7..754b68d56d 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_client.cc @@ -89,7 +89,7 @@ absl::Status MoqtClient::ConnectInner(std::string path, } MoqtSessionParameters parameters; - parameters.version = MoqtVersion::kDraft01; + parameters.version = MoqtVersion::kDraft02; parameters.perspective = quic::Perspective::IS_CLIENT, parameters.using_webtrans = true; parameters.path = ""; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h index 9248114c2f..246e8412ea 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_mock_visitor.h @@ -31,7 +31,7 @@ struct MockSessionCallbacks { class MockLocalTrackVisitor : public LocalTrack::Visitor { public: - MOCK_METHOD(std::optional, OnSubscribeRequestForPast, + MOCK_METHOD(std::optional, OnSubscribeForPast, (const SubscribeWindow& window), (override)); }; @@ -42,10 +42,10 @@ class MockRemoteTrackVisitor : public RemoteTrack::Visitor { std::optional error_reason_phrase), (override)); MOCK_METHOD(void, OnObjectFragment, - (const FullTrackName& full_track_name, uint32_t stream_id, - uint64_t group_sequence, uint64_t object_sequence, - uint64_t object_send_order, absl::string_view object, - bool end_of_message), + (const FullTrackName& full_track_name, uint64_t group_sequence, + uint64_t object_sequence, uint64_t object_send_order, + MoqtForwardingPreference forwarding_preference, + absl::string_view object, bool end_of_message), (override)); }; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc index e811c6df80..1c0f51b600 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/moqt/tools/moqt_server.cc @@ -33,7 +33,7 @@ quic::WebTransportRequestCallback CreateWebTransportCallback( parameters.perspective = quic::Perspective::IS_SERVER; parameters.path = path; parameters.using_webtrans = true; - parameters.version = MoqtVersion::kDraft01; + parameters.version = MoqtVersion::kDraft02; parameters.deliver_partial_objects = false; return std::make_unique(session, parameters, *std::move(callbacks)); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.cc index 18d93d96e5..0f95d006b0 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.cc @@ -4,9 +4,22 @@ #include "quiche/quic/test_tools/fake_proof_source_handle.h" +#include +#include +#include +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "quiche/quic/core/crypto/proof_source.h" #include "quiche/quic/core/quic_connection_id.h" #include "quiche/quic/core/quic_types.h" #include "quiche/quic/platform/api/quic_bug_tracker.h" +#include "quiche/quic/platform/api/quic_socket_address.h" +#include "quiche/common/platform/api/quiche_logging.h" +#include "quiche/common/platform/api/quiche_reference_counted.h" namespace quic { namespace test { @@ -53,12 +66,12 @@ ComputeSignatureResult ComputeSignatureNow( FakeProofSourceHandle::FakeProofSourceHandle( ProofSource* delegate, ProofSourceHandleCallback* callback, Action select_cert_action, Action compute_signature_action, - QuicDelayedSSLConfig dealyed_ssl_config) + QuicDelayedSSLConfig delayed_ssl_config) : delegate_(delegate), callback_(callback), select_cert_action_(select_cert_action), compute_signature_action_(compute_signature_action), - dealyed_ssl_config_(dealyed_ssl_config) {} + delayed_ssl_config_(delayed_ssl_config) {} void FakeProofSourceHandle::CloseHandle() { select_cert_op_.reset(); @@ -87,15 +100,16 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate( if (select_cert_action_ == Action::DELEGATE_ASYNC || select_cert_action_ == Action::FAIL_ASYNC) { select_cert_op_.emplace(delegate_, callback_, select_cert_action_, - all_select_cert_args_.back(), dealyed_ssl_config_); + all_select_cert_args_.back(), delayed_ssl_config_); return QUIC_PENDING; } else if (select_cert_action_ == Action::FAIL_SYNC || select_cert_action_ == Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) { callback()->OnSelectCertificateDone( /*ok=*/false, - /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view(), + /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/false, dealyed_ssl_config_); + /*cert_matched_sni=*/false); return QUIC_FAILURE; } @@ -107,10 +121,11 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate( bool ok = chain && !chain->certs.empty(); callback_->OnSelectCertificateDone( - ok, /*is_sync=*/true, chain.get(), - /*handshake_hints=*/absl::string_view(), + ok, /*is_sync=*/true, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/cert_matched_sni, dealyed_ssl_config_); + /*cert_matched_sni=*/cert_matched_sni); return ok ? QUIC_SUCCESS : QUIC_FAILURE; } @@ -177,19 +192,19 @@ int FakeProofSourceHandle::NumPendingOperations() const { FakeProofSourceHandle::SelectCertOperation::SelectCertOperation( ProofSource* delegate, ProofSourceHandleCallback* callback, Action action, - SelectCertArgs args, QuicDelayedSSLConfig dealyed_ssl_config) + SelectCertArgs args, QuicDelayedSSLConfig delayed_ssl_config) : PendingOperation(delegate, callback, action), args_(std::move(args)), - dealyed_ssl_config_(dealyed_ssl_config) {} + delayed_ssl_config_(delayed_ssl_config) {} void FakeProofSourceHandle::SelectCertOperation::Run() { if (action_ == Action::FAIL_ASYNC) { callback_->OnSelectCertificateDone( /*ok=*/false, - /*is_sync=*/false, nullptr, - /*handshake_hints=*/absl::string_view(), + /*is_sync=*/false, + ProofSourceHandleCallback::LocalSSLConfig{nullptr, delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/false, dealyed_ssl_config_); + /*cert_matched_sni=*/false); } else if (action_ == Action::DELEGATE_ASYNC) { bool cert_matched_sni; quiche::QuicheReferenceCountedPointer chain = @@ -197,10 +212,11 @@ void FakeProofSourceHandle::SelectCertOperation::Run() { args_.hostname, &cert_matched_sni); bool ok = chain && !chain->certs.empty(); callback_->OnSelectCertificateDone( - ok, /*is_sync=*/false, chain.get(), - /*handshake_hints=*/absl::string_view(), + ok, /*is_sync=*/false, + ProofSourceHandleCallback::LocalSSLConfig{chain.get(), + delayed_ssl_config_}, /*ticket_encryption_key=*/absl::string_view(), - /*cert_matched_sni=*/cert_matched_sni, dealyed_ssl_config_); + /*cert_matched_sni=*/cert_matched_sni); } else { QUIC_BUG(quic_bug_10139_1) << "Unexpected action: " << static_cast(action_); diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.h index 960544a821..f6d0935efc 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/fake_proof_source_handle.h @@ -31,11 +31,11 @@ class FakeProofSourceHandle : public ProofSourceHandle { }; // |delegate| must do cert selection and signature synchronously. - // |dealyed_ssl_config| is the config passed to OnSelectCertificateDone. + // |delayed_ssl_config| is the config passed to OnSelectCertificateDone. FakeProofSourceHandle( ProofSource* delegate, ProofSourceHandleCallback* callback, Action select_cert_action, Action compute_signature_action, - QuicDelayedSSLConfig dealyed_ssl_config = QuicDelayedSSLConfig()); + QuicDelayedSSLConfig delayed_ssl_config = QuicDelayedSSLConfig()); ~FakeProofSourceHandle() override = default; @@ -148,7 +148,7 @@ class FakeProofSourceHandle : public ProofSourceHandle { SelectCertOperation(ProofSource* delegate, ProofSourceHandleCallback* callback, Action action, SelectCertArgs args, - QuicDelayedSSLConfig dealyed_ssl_config); + QuicDelayedSSLConfig delayed_ssl_config); ~SelectCertOperation() override = default; @@ -156,7 +156,7 @@ class FakeProofSourceHandle : public ProofSourceHandle { private: const SelectCertArgs args_; - const QuicDelayedSSLConfig dealyed_ssl_config_; + const QuicDelayedSSLConfig delayed_ssl_config_; }; class ComputeSignatureOperation : public PendingOperation { @@ -183,7 +183,7 @@ class FakeProofSourceHandle : public ProofSourceHandle { Action select_cert_action_ = Action::DELEGATE_SYNC; // Action for the next compute signature operation. Action compute_signature_action_ = Action::DELEGATE_SYNC; - const QuicDelayedSSLConfig dealyed_ssl_config_; + const QuicDelayedSSLConfig delayed_ssl_config_; std::optional select_cert_op_; std::optional compute_signature_op_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc index 5b6678565b..d3c26bb8bf 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.cc @@ -137,57 +137,64 @@ class RecordingProofVerifier : public ProofVerifier { }; } // namespace -class MockableQuicClientDefaultNetworkHelper - : public QuicClientDefaultNetworkHelper { - public: - using QuicClientDefaultNetworkHelper::QuicClientDefaultNetworkHelper; - ~MockableQuicClientDefaultNetworkHelper() override = default; - - void ProcessPacket(const QuicSocketAddress& self_address, - const QuicSocketAddress& peer_address, - const QuicReceivedPacket& packet) override { - QuicClientDefaultNetworkHelper::ProcessPacket(self_address, peer_address, - packet); - if (track_last_incoming_packet_) { - last_incoming_packet_ = packet.Clone(); - } +void MockableQuicClientDefaultNetworkHelper::ProcessPacket( + const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, const QuicReceivedPacket& packet) { + QuicClientDefaultNetworkHelper::ProcessPacket(self_address, peer_address, + packet); + if (track_last_incoming_packet_) { + last_incoming_packet_ = packet.Clone(); } +} - QuicPacketWriter* CreateQuicPacketWriter() override { - QuicPacketWriter* writer = - QuicClientDefaultNetworkHelper::CreateQuicPacketWriter(); - if (!test_writer_) { - return writer; - } - test_writer_->set_writer(writer); - return test_writer_; +bool MockableQuicClientDefaultNetworkHelper::CreateUDPSocketAndBind( + QuicSocketAddress server_address, QuicIpAddress bind_to_address, + int bind_to_port) { + bool result = QuicClientDefaultNetworkHelper::CreateUDPSocketAndBind( + server_address, bind_to_address, bind_to_port); + if (result && socket_fd_configurator_ != nullptr) { + socket_fd_configurator_(GetLatestFD()); } + return result; +} - const QuicReceivedPacket* last_incoming_packet() { - return last_incoming_packet_.get(); +QuicPacketWriter* +MockableQuicClientDefaultNetworkHelper::CreateQuicPacketWriter() { + QuicPacketWriter* writer = + QuicClientDefaultNetworkHelper::CreateQuicPacketWriter(); + if (!test_writer_) { + return writer; } + test_writer_->set_writer(writer); + return test_writer_; +} - void set_track_last_incoming_packet(bool track) { - track_last_incoming_packet_ = track; - } +void MockableQuicClientDefaultNetworkHelper::set_socket_fd_configurator( + quiche::MultiUseCallback socket_fd_configurator) { + socket_fd_configurator_ = std::move(socket_fd_configurator); +} - void UseWriter(QuicPacketWriterWrapper* writer) { - QUICHE_CHECK(test_writer_ == nullptr); - test_writer_ = writer; - } +const QuicReceivedPacket* +MockableQuicClientDefaultNetworkHelper::last_incoming_packet() { + return last_incoming_packet_.get(); +} - void set_peer_address(const QuicSocketAddress& address) { - QUICHE_CHECK(test_writer_ != nullptr); - test_writer_->set_peer_address(address); - } +void MockableQuicClientDefaultNetworkHelper::set_track_last_incoming_packet( + bool track) { + track_last_incoming_packet_ = track; +} - private: - QuicPacketWriterWrapper* test_writer_ = nullptr; - // The last incoming packet, iff |track_last_incoming_packet_| is true. - std::unique_ptr last_incoming_packet_; - // If true, copy each packet from ProcessPacket into |last_incoming_packet_| - bool track_last_incoming_packet_ = false; -}; +void MockableQuicClientDefaultNetworkHelper::UseWriter( + QuicPacketWriterWrapper* writer) { + QUICHE_CHECK(test_writer_ == nullptr); + test_writer_ = writer; +} + +void MockableQuicClientDefaultNetworkHelper::set_peer_address( + const QuicSocketAddress& address) { + QUICHE_CHECK(test_writer_ != nullptr); + test_writer_->set_peer_address(address); +} MockableQuicClient::MockableQuicClient( QuicSocketAddress server_address, const QuicServerId& server_id, diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h index 3dbd524df4..4cf4ae7910 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_client.h @@ -28,7 +28,43 @@ class QuicPacketWriterWrapper; namespace test { -class MockableQuicClientDefaultNetworkHelper; +class MockableQuicClientDefaultNetworkHelper + : public QuicClientDefaultNetworkHelper { + public: + using QuicClientDefaultNetworkHelper::QuicClientDefaultNetworkHelper; + ~MockableQuicClientDefaultNetworkHelper() override = default; + + void ProcessPacket(const QuicSocketAddress& self_address, + const QuicSocketAddress& peer_address, + const QuicReceivedPacket& packet) override; + + bool CreateUDPSocketAndBind(QuicSocketAddress server_address, + QuicIpAddress bind_to_address, + int bind_to_port) override; + + QuicPacketWriter* CreateQuicPacketWriter() override; + + void set_socket_fd_configurator( + quiche::MultiUseCallback socket_fd_configurator); + + const QuicReceivedPacket* last_incoming_packet(); + + void set_track_last_incoming_packet(bool track); + + void UseWriter(QuicPacketWriterWrapper* writer); + + void set_peer_address(const QuicSocketAddress& address); + + private: + QuicPacketWriterWrapper* test_writer_ = nullptr; + // The last incoming packet, iff |track_last_incoming_packet_| is true. + std::unique_ptr last_incoming_packet_; + // If true, copy each packet from ProcessPacket into |last_incoming_packet_| + bool track_last_incoming_packet_ = false; + // If set, |socket_fd_configurator_| will be called after a socket fd is + // created. + quiche::MultiUseCallback socket_fd_configurator_; +}; // A quic client which allows mocking out reads and writes. class MockableQuicClient : public QuicDefaultClient { diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc index 8ffb8e817b..58277df00e 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.cc @@ -447,6 +447,11 @@ bool NoOpFramerVisitor::OnAckFrequencyFrame( return true; } +bool NoOpFramerVisitor::OnResetStreamAtFrame( + const QuicResetStreamAtFrame& /*frame*/) { + return true; +} + bool NoOpFramerVisitor::IsValidStatelessResetToken( const StatelessResetToken& /*token*/) const { return false; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h index 8fdaf98b14..7de2c2adec 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h @@ -20,6 +20,7 @@ #include "quiche/quic/core/congestion_control/loss_detection_interface.h" #include "quiche/quic/core/congestion_control/send_algorithm_interface.h" #include "quiche/quic/core/crypto/transport_parameters.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/http/http_decoder.h" #include "quiche/quic/core/http/quic_server_session_base.h" #include "quiche/quic/core/http/quic_spdy_client_session_base.h" @@ -353,6 +354,8 @@ class MockFramerVisitor : public QuicFramerVisitorInterface { (override)); MOCK_METHOD(bool, OnAckFrequencyFrame, (const QuicAckFrequencyFrame& frame), (override)); + MOCK_METHOD(bool, OnResetStreamAtFrame, (const QuicResetStreamAtFrame& frame), + (override)); MOCK_METHOD(void, OnPacketComplete, (), (override)); MOCK_METHOD(bool, IsValidStatelessResetToken, (const StatelessResetToken&), (const, override)); @@ -420,6 +423,7 @@ class NoOpFramerVisitor : public QuicFramerVisitorInterface { bool OnMessageFrame(const QuicMessageFrame& frame) override; bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override; bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override; + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override; void OnPacketComplete() override {} bool IsValidStatelessResetToken( const StatelessResetToken& token) const override; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simple_quic_framer.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simple_quic_framer.cc index fc502519a6..54ae4b33da 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simple_quic_framer.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/test_tools/simple_quic_framer.cc @@ -11,6 +11,7 @@ #include "absl/strings/string_view.h" #include "quiche/quic/core/crypto/quic_decrypter.h" #include "quiche/quic/core/crypto/quic_encrypter.h" +#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h" #include "quiche/quic/core/quic_types.h" namespace quic { @@ -210,6 +211,11 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { return true; } + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override { + reset_stream_at_frames_.push_back(frame); + return true; + } + void OnPacketComplete() override {} bool IsValidStatelessResetToken( @@ -312,6 +318,7 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { std::vector message_frames_; std::vector handshake_done_frames_; std::vector ack_frequency_frames_; + std::vector reset_stream_at_frames_; std::vector> stream_data_; std::vector> crypto_data_; EncryptionLevel last_decrypted_level_; diff --git a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc index e507c5e4ec..5ed77010ae 100644 --- a/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc +++ b/naiveproxy/src/net/third_party/quiche/src/quiche/quic/tools/quic_packet_printer_bin.cc @@ -213,6 +213,10 @@ class QuicPacketPrinter : public QuicFramerVisitorInterface { std::cerr << "OnAckFrequencyFrame: " << frame; return true; } + bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override { + std::cerr << "OnResetStreamAtFrame: " << frame; + return true; + } void OnPacketComplete() override { std::cerr << "OnPacketComplete\n"; } bool IsValidStatelessResetToken( const StatelessResetToken& /*token*/) const override { diff --git a/naiveproxy/src/net/tools/cachetool/cachetool.cc b/naiveproxy/src/net/tools/cachetool/cachetool.cc index f5baca42ef..cb036497ec 100644 --- a/naiveproxy/src/net/tools/cachetool/cachetool.cc +++ b/naiveproxy/src/net/tools/cachetool/cachetool.cc @@ -472,11 +472,11 @@ void ListDups(CommandMarshal* command_marshal) { response_info.headers->GetMimeType(&entry_data.mime_type); auto iter = md5_entries.find(hash); - if (iter == md5_entries.end()) - md5_entries.insert( - std::make_pair(hash, std::vector{entry_data})); - else + if (iter == md5_entries.end()) { + md5_entries.emplace(hash, std::vector{entry_data}); + } else { iter->second.push_back(entry_data); + } entry->Close(); entry = nullptr; diff --git a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc index a2d60bf0c5..66c7c5b31a 100644 --- a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc +++ b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool.cc @@ -506,7 +506,7 @@ int main(int argc, char** argv) { bssl::CertificateTrust trust = bssl::CertificateTrust::ForTrustedLeaf(); std::string trust_str = command_line.GetSwitchValueASCII("trust-leaf-cert"); if (!trust_str.empty()) { - absl::optional parsed_trust = + std::optional parsed_trust = bssl::CertificateTrust::FromDebugString(trust_str); if (!parsed_trust) { std::cerr << "ERROR: invalid leaf trust string " << trust_str << "\n"; @@ -523,7 +523,7 @@ int main(int argc, char** argv) { if (command_line.HasSwitch("root-trust")) { std::string trust_str = command_line.GetSwitchValueASCII("root-trust"); - absl::optional parsed_trust = + std::optional parsed_trust = bssl::CertificateTrust::FromDebugString(trust_str); if (!parsed_trust) { std::cerr << "ERROR: invalid root trust string " << trust_str << "\n"; diff --git a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool_util.cc b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool_util.cc index 02aa3b5fcb..2dfda031bb 100644 --- a/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool_util.cc +++ b/naiveproxy/src/net/tools/cert_verify_tool/cert_verify_tool_util.cc @@ -122,7 +122,7 @@ void PrintCertError(const std::string& error, const CertInput& cert) { std::string FingerPrintCryptoBuffer(const CRYPTO_BUFFER* cert_handle) { net::SHA256HashValue hash = net::X509Certificate::CalculateFingerprint256(cert_handle); - return base::HexEncode(hash.data, std::size(hash.data)); + return base::HexEncode(hash.data); } std::string SubjectFromX509Certificate(const net::X509Certificate* cert) { diff --git a/naiveproxy/src/net/tools/cert_verify_tool/verify_using_path_builder.cc b/naiveproxy/src/net/tools/cert_verify_tool/verify_using_path_builder.cc index 934920c286..4ae94278ec 100644 --- a/naiveproxy/src/net/tools/cert_verify_tool/verify_using_path_builder.cc +++ b/naiveproxy/src/net/tools/cert_verify_tool/verify_using_path_builder.cc @@ -57,7 +57,7 @@ bool DumpParsedCertificateChain(const base::FilePath& file_path, // Returns a hex-encoded sha256 of the DER-encoding of |cert|. std::string FingerPrintParsedCertificate(const bssl::ParsedCertificate* cert) { std::string hash = crypto::SHA256HashString(cert->der_cert().AsStringView()); - return base::HexEncode(hash.data(), hash.size()); + return base::HexEncode(hash); } std::string SubjectToString(const bssl::RDNSequence& parsed_subject) { @@ -96,7 +96,7 @@ void PrintResultPath(const bssl::CertPathBuilderResultPath* result_path, std::cout << "Certificate policies:\n"; for (const auto& policy : result_path->user_constrained_policy_set) { CBS cbs; - CBS_init(&cbs, policy.UnsafeData(), policy.Length()); + CBS_init(&cbs, policy.data(), policy.size()); bssl::UniquePtr policy_text(CBS_asn1_oid_to_text(&cbs)); if (policy_text) { std::cout << " " << policy_text.get() << "\n"; diff --git a/naiveproxy/src/net/tools/naive/naive_connection.cc b/naiveproxy/src/net/tools/naive/naive_connection.cc index e04d8df007..f5e4b0fe03 100644 --- a/naiveproxy/src/net/tools/naive/naive_connection.cc +++ b/naiveproxy/src/net/tools/naive/naive_connection.cc @@ -53,7 +53,6 @@ NaiveConnection::NaiveConnection( ClientProtocol protocol, std::unique_ptr padding_detector_delegate, const ProxyInfo& proxy_info, - const SSLConfig& server_ssl_config, RedirectResolver* resolver, HttpNetworkSession* session, const NetworkAnonymizationKey& network_anonymization_key, @@ -64,7 +63,6 @@ NaiveConnection::NaiveConnection( protocol_(protocol), padding_detector_delegate_(std::move(padding_detector_delegate)), proxy_info_(proxy_info), - server_ssl_config_(server_ssl_config), resolver_(resolver), session_(session), network_anonymization_key_(network_anonymization_key), @@ -277,7 +275,7 @@ int NaiveConnection::DoConnectServer() { // Ignores socket limit set by socket pool for this type of socket. return InitSocketHandleForHttpRequest( std::move(endpoint), LOAD_IGNORE_LIMITS, MAXIMUM_PRIORITY, session_, - proxy_info_, server_ssl_config_, PRIVACY_MODE_DISABLED, + proxy_info_, {}, PRIVACY_MODE_DISABLED, network_anonymization_key_, SecureDnsPolicy::kDisable, SocketTag(), net_log_, server_socket_handle_.get(), io_callback_, ClientSocketPool::ProxyAuthCallback()); diff --git a/naiveproxy/src/net/tools/naive/naive_connection.h b/naiveproxy/src/net/tools/naive/naive_connection.h index 95fc1a7984..83b14fff28 100644 --- a/naiveproxy/src/net/tools/naive/naive_connection.h +++ b/naiveproxy/src/net/tools/naive/naive_connection.h @@ -41,7 +41,6 @@ class NaiveConnection { ClientProtocol protocol, std::unique_ptr padding_detector_delegate, const ProxyInfo& proxy_info, - const SSLConfig& server_ssl_config, RedirectResolver* resolver, HttpNetworkSession* session, const NetworkAnonymizationKey& network_anonymization_key, @@ -95,7 +94,6 @@ class NaiveConnection { ClientProtocol protocol_; std::unique_ptr padding_detector_delegate_; const ProxyInfo& proxy_info_; - const SSLConfig& server_ssl_config_; RedirectResolver* resolver_; HttpNetworkSession* session_; const NetworkAnonymizationKey& network_anonymization_key_; diff --git a/naiveproxy/src/net/tools/naive/naive_proxy.cc b/naiveproxy/src/net/tools/naive/naive_proxy.cc index ce07b9162e..0c50b0de2c 100644 --- a/naiveproxy/src/net/tools/naive/naive_proxy.cc +++ b/naiveproxy/src/net/tools/naive/naive_proxy.cc @@ -59,14 +59,6 @@ NaiveProxy::NaiveProxy(std::unique_ptr listen_socket, proxy_info_.set_traffic_annotation( net::MutableNetworkTrafficAnnotationTag(traffic_annotation_)); - // See HttpStreamFactory::Job::DoInitConnectionImpl() - server_ssl_config_.alpn_protos = session_->GetAlpnProtos(); - server_ssl_config_.application_settings = session_->GetApplicationSettings(); - server_ssl_config_.ignore_certificate_errors = - session_->params().ignore_certificate_errors; - // TODO(https://crbug.com/964642): Also enable 0-RTT for TLS proxies. - server_ssl_config_.early_data_enabled = session_->params().enable_early_data; - for (int i = 0; i < concurrency_; i++) { network_anonymization_keys_.push_back( NetworkAnonymizationKey::CreateTransient()); @@ -137,8 +129,8 @@ void NaiveProxy::DoConnect() { const auto& nak = network_anonymization_keys_[tunnel_session_id]; auto connection_ptr = std::make_unique( last_id_, protocol_, std::move(padding_detector_delegate), proxy_info_, - server_ssl_config_, resolver_, session_, nak, net_log_, - std::move(socket), traffic_annotation_); + resolver_, session_, nak, net_log_, std::move(socket), + traffic_annotation_); auto* connection = connection_ptr.get(); connection_by_id_[connection->id()] = std::move(connection_ptr); int result = connection->Connect( diff --git a/naiveproxy/src/net/tools/naive/naive_proxy.h b/naiveproxy/src/net/tools/naive/naive_proxy.h index 2c5b6ce2ea..626ac7e950 100644 --- a/naiveproxy/src/net/tools/naive/naive_proxy.h +++ b/naiveproxy/src/net/tools/naive/naive_proxy.h @@ -67,7 +67,6 @@ class NaiveProxy { std::string listen_pass_; int concurrency_; ProxyInfo proxy_info_; - SSLConfig server_ssl_config_; RedirectResolver* resolver_; HttpNetworkSession* session_; NetLogWithSource net_log_; diff --git a/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.cc b/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.cc index 90d00b014f..1ca7ccbf9a 100644 --- a/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.cc +++ b/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.cc @@ -41,7 +41,7 @@ void QuicSimpleServerPacketWriter::SetWritable() { write_blocked_ = false; } -absl::optional QuicSimpleServerPacketWriter::MessageTooBigErrorCode() +std::optional QuicSimpleServerPacketWriter::MessageTooBigErrorCode() const { return ERR_MSG_TOO_BIG; } diff --git a/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.h b/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.h index 5685784dfb..00ed4996b3 100644 --- a/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.h +++ b/naiveproxy/src/net/tools/quic/quic_simple_server_packet_writer.h @@ -50,7 +50,7 @@ class QuicSimpleServerPacketWriter : public quic::QuicPacketWriter { // quic::QuicPacketWriter implementation: bool IsWriteBlocked() const override; void SetWritable() override; - absl::optional MessageTooBigErrorCode() const override; + std::optional MessageTooBigErrorCode() const override; quic::QuicByteCount GetMaxPacketSize( const quic::QuicSocketAddress& peer_address) const override; bool SupportsReleaseTime() const override; diff --git a/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc b/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc index a09c04cc34..dfb89e3c77 100644 --- a/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc +++ b/naiveproxy/src/net/tools/quic/synchronous_host_resolver.cc @@ -5,6 +5,7 @@ #include "net/tools/quic/synchronous_host_resolver.h" #include +#include #include #include "base/at_exit.h" @@ -22,7 +23,6 @@ #include "net/dns/host_resolver.h" #include "net/log/net_log.h" #include "net/log/net_log_with_source.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/scheme_host_port.h" namespace net { @@ -70,7 +70,7 @@ void ResolverThread::Run() { // tool not used by net/ consumers. std::unique_ptr request = resolver->CreateRequest(scheme_host_port_, NetworkAnonymizationKey(), - NetLogWithSource(), absl::nullopt); + NetLogWithSource(), std::nullopt); base::RunLoop run_loop; rv_ = request->Start(base::BindOnce(&ResolverThread::OnResolutionComplete, diff --git a/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc b/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc index 5be48e64e7..811f9f8d3f 100644 --- a/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc +++ b/naiveproxy/src/net/tools/root_store_tool/root_store_tool.cc @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -27,7 +28,6 @@ #include "crypto/openssl_util.h" #include "crypto/sha2.h" #include "net/cert/root_store_proto_full/root_store.pb.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/boringssl/src/include/openssl/bio.h" #include "third_party/boringssl/src/include/openssl/err.h" #include "third_party/boringssl/src/include/openssl/pem.h" @@ -38,8 +38,8 @@ using chrome_root_store::RootStore; namespace { // Returns a map from hex-encoded SHA-256 hash to DER certificate, or -// `absl::nullopt` if not found. -absl::optional> DecodeCerts( +// `std::nullopt` if not found. +std::optional> DecodeCerts( base::StringPiece in) { // TODO(https://crbug.com/1216547): net/cert/pem.h has a much nicer API, but // it would require some build refactoring to avoid a circular dependency. @@ -47,7 +47,7 @@ absl::optional> DecodeCerts( // net/cert/internal, which it may not. bssl::UniquePtr bio(BIO_new_mem_buf(in.data(), in.size())); if (!bio) { - return absl::nullopt; + return std::nullopt; } std::map certs; for (;;) { @@ -63,7 +63,7 @@ absl::optional> DecodeCerts( break; } LOG(ERROR) << "Error reading PEM."; - return absl::nullopt; + return std::nullopt; } bssl::UniquePtr scoped_name(name); bssl::UniquePtr scoped_header(header); @@ -71,7 +71,7 @@ absl::optional> DecodeCerts( if (strcmp(name, "CERTIFICATE") != 0) { LOG(ERROR) << "Found PEM block of type " << name << " instead of CERTIFICATE"; - return absl::nullopt; + return std::nullopt; } std::string sha256_hex = base::ToLowerASCII(base::HexEncode(crypto::SHA256Hash( @@ -81,21 +81,21 @@ absl::optional> DecodeCerts( return std::move(certs); } -absl::optional ReadTextRootStore( +std::optional ReadTextRootStore( const base::FilePath& root_store_path, const base::FilePath& certs_path) { std::string root_store_text; if (!base::ReadFileToString(base::MakeAbsoluteFilePath(root_store_path), &root_store_text)) { LOG(ERROR) << "Could not read " << root_store_path; - return absl::nullopt; + return std::nullopt; } RootStore root_store; if (!google::protobuf::TextFormat::ParseFromString(root_store_text, &root_store)) { LOG(ERROR) << "Could not parse " << root_store_path; - return absl::nullopt; + return std::nullopt; } std::map certs; @@ -104,12 +104,12 @@ absl::optional ReadTextRootStore( if (!base::ReadFileToString(base::MakeAbsoluteFilePath(certs_path), &certs_data)) { LOG(ERROR) << "Could not read " << certs_path; - return absl::nullopt; + return std::nullopt; } auto certs_opt = DecodeCerts(certs_data); if (!certs_opt) { LOG(ERROR) << "Could not decode " << certs_path; - return absl::nullopt; + return std::nullopt; } certs = std::move(*certs_opt); } @@ -124,7 +124,7 @@ absl::optional ReadTextRootStore( auto iter = certs.find(anchor.sha256_hex()); if (iter == certs.end()) { LOG(ERROR) << "Could not find certificate " << anchor.sha256_hex(); - return absl::nullopt; + return std::nullopt; } // Remove the certificate from `certs`. This both checks for duplicate @@ -136,7 +136,7 @@ absl::optional ReadTextRootStore( if (!certs.empty()) { LOG(ERROR) << "Unused certificate (SHA-256 hash " << certs.begin()->first << ") in " << certs_path; - return absl::nullopt; + return std::nullopt; } return std::move(root_store); @@ -240,8 +240,7 @@ bool WriteEvCppFile(const RootStore& root_store, // Chrome Root Store textprotos. const int kMaxPolicyOids = 2; int oids_size = anchor.ev_policy_oids_size(); - std::string hexencode_hash = - base::HexEncode(sha256_hash.data(), sha256_hash.size()); + std::string hexencode_hash = base::HexEncode(sha256_hash); if (oids_size > kMaxPolicyOids) { PLOG(ERROR) << hexencode_hash << " has too many OIDs!"; return false; @@ -301,7 +300,7 @@ int main(int argc, char** argv) { return 1; } - absl::optional root_store = + std::optional root_store = ReadTextRootStore(root_store_path, certs_path); if (!root_store) { return 1; diff --git a/naiveproxy/src/net/tools/testserver/run_testserver.cc b/naiveproxy/src/net/tools/testserver/run_testserver.cc index d110d2de57..774c8f0167 100644 --- a/naiveproxy/src/net/tools/testserver/run_testserver.cc +++ b/naiveproxy/src/net/tools/testserver/run_testserver.cc @@ -52,7 +52,7 @@ int main(int argc, const char* argv[]) { } // If populated, EmbeddedTestServer is used instead of the SpawnedTestServer. - absl::optional embedded_test_server_type; + std::optional embedded_test_server_type; net::SpawnedTestServer::Type server_type; if (command_line->HasSwitch("http")) { diff --git a/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc b/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc index 2236115745..5c0eb56cbe 100644 --- a/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc +++ b/naiveproxy/src/net/tools/transport_security_state_generator/input_file_parsers.cc @@ -339,13 +339,13 @@ bool ParseJSON(base::StringPiece hsts_json, "test", "public-suffix", "google", "custom", "bulk-legacy", "bulk-18-weeks", "bulk-1-year", "public-suffix-requested"}; - absl::optional hsts_value = base::JSONReader::Read(hsts_json); + std::optional hsts_value = base::JSONReader::Read(hsts_json); if (!hsts_value.has_value() || !hsts_value->is_dict()) { LOG(ERROR) << "Could not parse the input HSTS JSON file"; return false; } - absl::optional pins_value = base::JSONReader::Read(pins_json); + std::optional pins_value = base::JSONReader::Read(pins_json); if (!pins_value.has_value()) { LOG(ERROR) << "Could not parse the input pins JSON file"; return false; @@ -404,9 +404,9 @@ bool ParseJSON(base::StringPiece hsts_json, return false; } - pins_map[*maybe_hostname] = std::make_pair( - *maybe_pinset, - parsed->FindBool(kIncludeSubdomainsJSONKey).value_or(false)); + pins_map[*maybe_hostname] = + std::pair(*maybe_pinset, + parsed->FindBool(kIncludeSubdomainsJSONKey).value_or(false)); } const base::Value::List* preload_entries_list = diff --git a/naiveproxy/src/net/url_request/redirect_info.cc b/naiveproxy/src/net/url_request/redirect_info.cc index 4042f029b4..07e0cc4f46 100644 --- a/naiveproxy/src/net/url_request/redirect_info.cc +++ b/naiveproxy/src/net/url_request/redirect_info.cc @@ -37,7 +37,7 @@ std::string ComputeMethodForRedirect(const std::string& method, // policy that should be used for the request. ReferrerPolicy ProcessReferrerPolicyHeaderOnRedirect( ReferrerPolicy original_referrer_policy, - const absl::optional& referrer_policy_header) { + const std::optional& referrer_policy_header) { ReferrerPolicy new_policy = original_referrer_policy; std::vector policy_tokens; if (referrer_policy_header) { @@ -114,7 +114,7 @@ RedirectInfo RedirectInfo::ComputeRedirectInfo( const std::string& original_referrer, int http_status_code, const GURL& new_location, - const absl::optional& referrer_policy_header, + const std::optional& referrer_policy_header, bool insecure_scheme_was_upgraded, bool copy_fragment, bool is_signed_exchange_fallback_redirect) { diff --git a/naiveproxy/src/net/url_request/redirect_info.h b/naiveproxy/src/net/url_request/redirect_info.h index 5b4dae0aad..810eaf97d9 100644 --- a/naiveproxy/src/net/url_request/redirect_info.h +++ b/naiveproxy/src/net/url_request/redirect_info.h @@ -5,13 +5,13 @@ #ifndef NET_URL_REQUEST_REDIRECT_INFO_H_ #define NET_URL_REQUEST_REDIRECT_INFO_H_ +#include #include #include "base/time/time.h" #include "net/base/net_export.h" #include "net/cookies/site_for_cookies.h" #include "net/url_request/referrer_policy.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -47,7 +47,7 @@ struct NET_EXPORT RedirectInfo { // The new location URL of the redirect response. const GURL& new_location, // Referrer-Policy header of the redirect response. - const absl::optional& referrer_policy_header, + const std::optional& referrer_policy_header, // Whether the URL was upgraded to HTTPS due to upgrade-insecure-requests. bool insecure_scheme_was_upgraded, // This method copies the URL fragment of the original URL to the new URL diff --git a/naiveproxy/src/net/url_request/redirect_util.cc b/naiveproxy/src/net/url_request/redirect_util.cc index 63f2e68219..acbd43a718 100644 --- a/naiveproxy/src/net/url_request/redirect_util.cc +++ b/naiveproxy/src/net/url_request/redirect_util.cc @@ -21,8 +21,8 @@ void RedirectUtil::UpdateHttpRequest( const GURL& original_url, const std::string& original_method, const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers, + const std::optional>& removed_headers, + const std::optional& modified_headers, HttpRequestHeaders* request_headers, bool* should_clear_upload) { DCHECK(request_headers); @@ -89,14 +89,14 @@ void RedirectUtil::UpdateHttpRequest( } // static -absl::optional RedirectUtil::GetReferrerPolicyHeader( +std::optional RedirectUtil::GetReferrerPolicyHeader( const HttpResponseHeaders* response_headers) { if (!response_headers) - return absl::nullopt; + return std::nullopt; std::string referrer_policy_header; if (!response_headers->GetNormalizedHeader("Referrer-Policy", &referrer_policy_header)) { - return absl::nullopt; + return std::nullopt; } return referrer_policy_header; } diff --git a/naiveproxy/src/net/url_request/redirect_util.h b/naiveproxy/src/net/url_request/redirect_util.h index 3594f10c1f..4d538d809b 100644 --- a/naiveproxy/src/net/url_request/redirect_util.h +++ b/naiveproxy/src/net/url_request/redirect_util.h @@ -5,12 +5,12 @@ #ifndef NET_URL_REQUEST_REDIRECT_UTIL_H_ #define NET_URL_REQUEST_REDIRECT_UTIL_H_ +#include #include #include #include "base/memory/scoped_refptr.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -40,14 +40,14 @@ class RedirectUtil { const GURL& original_url, const std::string& original_method, const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers, + const std::optional>& removed_headers, + const std::optional& modified_headers, HttpRequestHeaders* request_headers, bool* should_clear_upload); // Returns the the "normalized" value of Referrer-Policy header if available. - // Otherwise returns absl::nullopt. - NET_EXPORT static absl::optional GetReferrerPolicyHeader( + // Otherwise returns std::nullopt. + NET_EXPORT static std::optional GetReferrerPolicyHeader( const HttpResponseHeaders* response_headers); NET_EXPORT static scoped_refptr diff --git a/naiveproxy/src/net/url_request/url_request.cc b/naiveproxy/src/net/url_request/url_request.cc index 1bd70e772a..1091a9f5ff 100644 --- a/naiveproxy/src/net/url_request/url_request.cc +++ b/naiveproxy/src/net/url_request/url_request.cc @@ -131,7 +131,7 @@ void ConvertRealLoadTimesToBlockingTimes(LoadTimingInfo* load_timing_info) { NetLogWithSource CreateNetLogWithSource( NetLog* net_log, - absl::optional net_log_source) { + std::optional net_log_source) { if (net_log_source) { return NetLogWithSource::Make(net_log, net_log_source.value()); } @@ -378,7 +378,7 @@ HttpResponseHeaders* URLRequest::response_headers() const { return response_info_.headers.get(); } -const absl::optional& URLRequest::auth_challenge_info() +const std::optional& URLRequest::auth_challenge_info() const { return response_info_.auth_challenge; } @@ -484,7 +484,7 @@ void URLRequest::set_first_party_url_policy( first_party_url_policy_ = first_party_url_policy; } -void URLRequest::set_initiator(const absl::optional& initiator) { +void URLRequest::set_initiator(const std::optional& initiator) { DCHECK(!is_pending_); DCHECK(!initiator.has_value() || initiator.value().opaque() || initiator.value().GetURL().is_valid()); @@ -577,7 +577,7 @@ URLRequest::URLRequest(base::PassKey pass_key, const URLRequestContext* context, NetworkTrafficAnnotationTag traffic_annotation, bool is_for_websockets, - absl::optional net_log_source) + std::optional net_log_source) : context_(context), net_log_(CreateNetLogWithSource(context->net_log(), net_log_source)), url_chain_(1, url), @@ -861,8 +861,8 @@ void URLRequest::NotifyResponseStarted(int net_error) { } void URLRequest::FollowDeferredRedirect( - const absl::optional>& removed_headers, - const absl::optional& modified_headers) { + const std::optional>& removed_headers, + const std::optional& modified_headers) { DCHECK(job_.get()); DCHECK_EQ(OK, status_); @@ -946,8 +946,8 @@ void URLRequest::PrepareToRestart() { void URLRequest::Redirect( const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers) { + const std::optional>& removed_headers, + const std::optional& modified_headers) { // This method always succeeds. Whether |job_| is allowed to redirect to // |redirect_info| is checked in URLRequestJob::CanFollowRedirect, before // NotifyReceivedRedirect. This means the delegate can assume that, if it @@ -1197,7 +1197,7 @@ IsolationInfo URLRequest::CreateIsolationInfoFromNetworkAnonymizationKey( url::Origin top_frame_origin = network_anonymization_key.GetTopFrameSite()->site_as_origin_; - absl::optional frame_origin; + std::optional frame_origin; if (network_anonymization_key.IsCrossSite()) { // If we know that the origin is cross site to the top level site, create an // empty origin to use as the frame origin for the isolation info. This diff --git a/naiveproxy/src/net/url_request/url_request.h b/naiveproxy/src/net/url_request/url_request.h index ce7074e047..859dcb00e8 100644 --- a/naiveproxy/src/net/url_request/url_request.h +++ b/naiveproxy/src/net/url_request/url_request.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -54,7 +55,6 @@ #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/redirect_info.h" #include "net/url_request/referrer_policy.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -218,7 +218,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { const URLRequestContext* context, NetworkTrafficAnnotationTag traffic_annotation, bool is_for_websockets, - absl::optional net_log_source); + std::optional net_log_source); URLRequest(const URLRequest&) = delete; URLRequest& operator=(const URLRequest&) = delete; @@ -302,7 +302,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { const IsolationInfo& isolation_info() const { return isolation_info_; } - const absl::optional& cookie_partition_key() const { + const std::optional& cookie_partition_key() const { return cookie_partition_key_; } @@ -362,9 +362,9 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Note: the initiator can be null for browser-initiated top level // navigations. This is different from a unique Origin (e.g. in sandboxed // iframes). - const absl::optional& initiator() const { return initiator_; } + const std::optional& initiator() const { return initiator_; } // This method may only be called before Start(). - void set_initiator(const absl::optional& initiator); + void set_initiator(const std::optional& initiator); // The request method. "GET" is the default value. The request method may // only be changed before Start() is called. Request methods are @@ -525,7 +525,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Get the SSL connection info. const SSLInfo& ssl_info() const { return response_info_.ssl_info; } - const absl::optional& auth_challenge_info() const; + const std::optional& auth_challenge_info() const; // Gets timing information related to the request. Events that have not yet // occurred are left uninitialized. After a second request starts, due to @@ -663,8 +663,8 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // |modified_headers| are changes applied to the request headers after // updating them for the redirect. void FollowDeferredRedirect( - const absl::optional>& removed_headers, - const absl::optional& modified_headers); + const std::optional>& removed_headers, + const std::optional& modified_headers); // One of the following two methods should be called in response to an // OnAuthRequired() callback (and only then). @@ -750,13 +750,13 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { return traffic_annotation_; } - const absl::optional>& + const std::optional>& accepted_stream_types() const { return accepted_stream_types_; } void set_accepted_stream_types( - const absl::optional>& + const std::optional>& types) { if (types) { DCHECK(!types->contains(net::SourceStream::SourceType::TYPE_NONE)); @@ -860,10 +860,9 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // Allow the URLRequestJob to redirect this request. If non-null, // |removed_headers| and |modified_headers| are changes // applied to the request headers after updating them for the redirect. - void Redirect( - const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers); + void Redirect(const RedirectInfo& redirect_info, + const std::optional>& removed_headers, + const std::optional& modified_headers); // Called by URLRequestJob to allow interception when a redirect occurs. void NotifyReceivedRedirect(const RedirectInfo& redirect_info, @@ -968,13 +967,13 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // partitioning is not enabled, or if the NIK has no top-frame site. // // Unpartitioned cookies are unaffected by this field. - absl::optional cookie_partition_key_ = absl::nullopt; + std::optional cookie_partition_key_ = std::nullopt; bool force_ignore_site_for_cookies_ = false; bool force_main_frame_for_same_site_cookies_ = false; CookieSettingOverrides cookie_setting_overrides_; - absl::optional initiator_; + std::optional initiator_; GURL delegate_redirect_url_; std::string method_; // "GET", "POST", etc. Case-sensitive. std::string referrer_; @@ -1087,7 +1086,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData { // If not null, the network service will not advertise any stream types // (via Accept-Encoding) that are not listed. Also, it will not attempt // decoding any non-listed stream types. - absl::optional> + std::optional> accepted_stream_types_; const NetworkTrafficAnnotationTag traffic_annotation_; diff --git a/naiveproxy/src/net/url_request/url_request_context.cc b/naiveproxy/src/net/url_request/url_request_context.cc index 9864694af1..d1ba7773ca 100644 --- a/naiveproxy/src/net/url_request/url_request_context.cc +++ b/naiveproxy/src/net/url_request/url_request_context.cc @@ -40,7 +40,6 @@ #include "net/ssl/ssl_config_service.h" #include "net/url_request/url_request.h" #include "net/url_request/url_request_job_factory.h" -#include "net/url_request/url_request_throttler_manager.h" #if BUILDFLAG(ENABLE_REPORTING) #include "net/network_error_logging/network_error_logging_service.h" @@ -52,7 +51,8 @@ namespace net { URLRequestContext::URLRequestContext( base::PassKey pass_key) - : url_requests_(std::make_unique>()), + : url_requests_(std::make_unique< + std::set>>()), bound_network_(handles::kInvalidNetworkHandle) {} URLRequestContext::~URLRequestContext() { @@ -133,7 +133,7 @@ std::unique_ptr URLRequestContext::CreateRequest( URLRequest::Delegate* delegate, NetworkTrafficAnnotationTag traffic_annotation, bool is_for_websockets, - const absl::optional net_log_source) const { + const std::optional net_log_source) const { return std::make_unique( base::PassKey(), url, priority, delegate, this, traffic_annotation, is_for_websockets, net_log_source); @@ -215,10 +215,6 @@ void URLRequestContext::set_job_factory( job_factory_storage_ = std::move(job_factory); job_factory_ = job_factory_storage_.get(); } -void URLRequestContext::set_throttler_manager( - std::unique_ptr throttler_manager) { - throttler_manager_ = std::move(throttler_manager); -} void URLRequestContext::set_quic_context( std::unique_ptr quic_context) { quic_context_ = std::move(quic_context); diff --git a/naiveproxy/src/net/url_request/url_request_context.h b/naiveproxy/src/net/url_request/url_request_context.h index 6b4f3a5145..5618d02062 100644 --- a/naiveproxy/src/net/url_request/url_request_context.h +++ b/naiveproxy/src/net/url_request/url_request_context.h @@ -9,7 +9,9 @@ #define NET_URL_REQUEST_URL_REQUEST_CONTEXT_H_ #include + #include +#include #include #include @@ -26,7 +28,6 @@ #include "net/net_buildflags.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "net/url_request/url_request.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { class CertVerifier; @@ -52,7 +53,6 @@ class TransportSecurityPersister; class TransportSecurityState; class URLRequest; class URLRequestJobFactory; -class URLRequestThrottlerManager; class URLRequestContextBuilder; #if BUILDFLAG(ENABLE_REPORTING) @@ -120,8 +120,8 @@ class NET_EXPORT URLRequestContext final { URLRequest::Delegate* delegate, NetworkTrafficAnnotationTag traffic_annotation, bool is_for_websockets = false, - const absl::optional net_log_source = - absl::nullopt) const; + const std::optional net_log_source = + std::nullopt) const; NetLog* net_log() const { return net_log_; } @@ -172,16 +172,11 @@ class NET_EXPORT URLRequestContext final { const URLRequestJobFactory* job_factory() const { return job_factory_; } - // May return nullptr. - URLRequestThrottlerManager* throttler_manager() const { - return throttler_manager_.get(); - } - QuicContext* quic_context() const { return quic_context_.get(); } // Gets the URLRequest objects that hold a reference to this // URLRequestContext. - std::set* url_requests() const { + std::set>* url_requests() const { return url_requests_.get(); } @@ -236,11 +231,11 @@ class NET_EXPORT URLRequestContext final { job_factory_ = job_factory; } - const absl::optional& cookie_deprecation_label() const { + const std::optional& cookie_deprecation_label() const { return cookie_deprecation_label_; } - void set_cookie_deprecation_label(const absl::optional& label) { + void set_cookie_deprecation_label(const std::optional& label) { cookie_deprecation_label_ = label; } @@ -272,8 +267,6 @@ class NET_EXPORT URLRequestContext final { std::unique_ptr state); void set_sct_auditing_delegate(std::unique_ptr delegate); void set_job_factory(std::unique_ptr job_factory); - void set_throttler_manager( - std::unique_ptr throttler_manager); void set_quic_context(std::unique_ptr quic_context); void set_http_user_agent_settings( std::unique_ptr http_user_agent_settings); @@ -307,7 +300,7 @@ class NET_EXPORT URLRequestContext final { void set_transport_security_persister( std::unique_ptr transport_security_persister); - raw_ptr net_log_ = nullptr; + raw_ptr net_log_ = nullptr; std::unique_ptr host_resolver_; std::unique_ptr cert_verifier_; @@ -332,8 +325,6 @@ class NET_EXPORT URLRequestContext final { std::unique_ptr job_factory_storage_; raw_ptr job_factory_ = nullptr; - std::unique_ptr throttler_manager_; - #if BUILDFLAG(ENABLE_REPORTING) // Must precede |reporting_service_| and |network_error_logging_service_| std::unique_ptr @@ -354,7 +345,8 @@ class NET_EXPORT URLRequestContext final { std::unique_ptr transport_security_persister_; - std::unique_ptr> url_requests_; + std::unique_ptr>> + url_requests_; // Enables Brotli Content-Encoding support. bool enable_brotli_ = false; @@ -368,7 +360,7 @@ class NET_EXPORT URLRequestContext final { // provided to a request when true. bool require_network_anonymization_key_ = false; - absl::optional cookie_deprecation_label_; + std::optional cookie_deprecation_label_; handles::NetworkHandle bound_network_; diff --git a/naiveproxy/src/net/url_request/url_request_context_builder.cc b/naiveproxy/src/net/url_request/url_request_context_builder.cc index 30a861d143..c4ba732823 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.cc +++ b/naiveproxy/src/net/url_request/url_request_context_builder.cc @@ -5,6 +5,7 @@ #include "net/url_request/url_request_context_builder.h" #include +#include #include #include #include @@ -49,8 +50,6 @@ #include "net/url_request/static_http_user_agent_settings.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" -#include "net/url_request/url_request_throttler_manager.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/url_constants.h" #if BUILDFLAG(ENABLE_REPORTING) @@ -246,7 +245,7 @@ void URLRequestContextBuilder::SetCreateHttpTransactionFactoryCallback( void URLRequestContextBuilder::BindToNetwork( handles::NetworkHandle network, - absl::optional options) { + std::optional options) { #if BUILDFLAG(IS_ANDROID) DCHECK(NetworkChangeNotifier::AreNetworkHandlesSupported()); // DNS lookups for this context will need to target `network`. NDK to do that @@ -428,11 +427,6 @@ std::unique_ptr URLRequestContextBuilder::Build() { context->set_quic_context(std::make_unique()); } - if (throttling_enabled_) { - context->set_throttler_manager( - std::make_unique()); - } - if (!proxy_resolution_service_) { #if !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID) // TODO(willchan): Switch to using this code when diff --git a/naiveproxy/src/net/url_request/url_request_context_builder.h b/naiveproxy/src/net/url_request/url_request_context_builder.h index e65bf6682b..66fd979eba 100644 --- a/naiveproxy/src/net/url_request/url_request_context_builder.h +++ b/naiveproxy/src/net/url_request/url_request_context_builder.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -44,7 +45,6 @@ #include "net/ssl/ssl_config_service.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h" #include "net/url_request/url_request_job_factory.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -276,10 +276,6 @@ class NET_EXPORT URLRequestContextBuilder { void SetSpdyAndQuicEnabled(bool spdy_enabled, bool quic_enabled); - void set_throttling_enabled(bool throttling_enabled) { - throttling_enabled_ = throttling_enabled; - } - void set_sct_auditing_delegate( std::unique_ptr sct_auditing_delegate); void set_quic_context(std::unique_ptr quic_context); @@ -358,7 +354,7 @@ class NET_EXPORT URLRequestContextBuilder { // Only implemented for Android (API level > 23). void BindToNetwork( handles::NetworkHandle network, - absl::optional options = absl::nullopt); + std::optional options = std::nullopt); // Creates a mostly self-contained URLRequestContext. May only be called once // per URLRequestContextBuilder. After this is called, the Builder can be @@ -410,10 +406,9 @@ class NET_EXPORT URLRequestContextBuilder { std::string user_agent_; std::unique_ptr http_user_agent_settings_; - absl::optional cookie_deprecation_label_; + std::optional cookie_deprecation_label_; bool http_cache_enabled_ = true; - bool throttling_enabled_ = false; bool cookie_store_set_by_client_ = false; bool suppress_setting_socket_performance_watcher_factory_for_testing_ = false; diff --git a/naiveproxy/src/net/url_request/url_request_filter.cc b/naiveproxy/src/net/url_request/url_request_filter.cc index 5689d01bfb..4736a76356 100644 --- a/naiveproxy/src/net/url_request/url_request_filter.cc +++ b/naiveproxy/src/net/url_request/url_request_filter.cc @@ -49,8 +49,8 @@ void URLRequestFilter::AddHostnameInterceptor( const std::string& hostname, std::unique_ptr interceptor) { DCHECK(OnMessageLoopForInterceptorAddition()); - DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(scheme, hostname))); - hostname_interceptor_map_[make_pair(scheme, hostname)] = + DCHECK_EQ(0u, hostname_interceptor_map_.count(std::pair(scheme, hostname))); + hostname_interceptor_map_[std::pair(scheme, hostname)] = std::move(interceptor); #ifndef NDEBUG @@ -58,7 +58,7 @@ void URLRequestFilter::AddHostnameInterceptor( for (const auto& pair : url_interceptor_map_) { const GURL& url = GURL(pair.first); HostnameInterceptorMap::const_iterator host_it = - hostname_interceptor_map_.find(make_pair(url.scheme(), url.host())); + hostname_interceptor_map_.find(std::pair(url.scheme(), url.host())); if (host_it != hostname_interceptor_map_.end()) NOTREACHED(); } @@ -68,7 +68,7 @@ void URLRequestFilter::AddHostnameInterceptor( void URLRequestFilter::RemoveHostnameHandler(const std::string& scheme, const std::string& hostname) { DCHECK(OnMessageLoopForInterceptorRemoval()); - int removed = hostname_interceptor_map_.erase(make_pair(scheme, hostname)); + int removed = hostname_interceptor_map_.erase(std::pair(scheme, hostname)); DCHECK(removed); } @@ -82,8 +82,8 @@ bool URLRequestFilter::AddUrlInterceptor( url_interceptor_map_[url.spec()] = std::move(interceptor); // Check to see if this URL is masked by a hostname handler. - DCHECK_EQ(0u, hostname_interceptor_map_.count(make_pair(url.scheme(), - url.host()))); + DCHECK_EQ( + 0u, hostname_interceptor_map_.count(std::pair(url.scheme(), url.host()))); return true; } @@ -114,7 +114,7 @@ std::unique_ptr URLRequestFilter::MaybeInterceptRequest( const std::string scheme = request->url().scheme(); { - auto it = hostname_interceptor_map_.find(make_pair(scheme, hostname)); + auto it = hostname_interceptor_map_.find(std::pair(scheme, hostname)); if (it != hostname_interceptor_map_.end()) job = it->second->MaybeInterceptRequest(request); } diff --git a/naiveproxy/src/net/url_request/url_request_http_job.cc b/naiveproxy/src/net/url_request/url_request_http_job.cc index 3afc552649..d007b8623e 100644 --- a/naiveproxy/src/net/url_request/url_request_http_job.cc +++ b/naiveproxy/src/net/url_request/url_request_http_job.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -93,9 +94,7 @@ #include "net/url_request/url_request_error_job.h" #include "net/url_request/url_request_job_factory.h" #include "net/url_request/url_request_redirect_job.h" -#include "net/url_request/url_request_throttler_manager.h" #include "net/url_request/websocket_handshake_userdata_key.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" #include "url/url_constants.h" @@ -125,7 +124,7 @@ base::Value::Dict FirstPartySetMetadataNetLogParams( const int64_t* const fps_cache_filter) { base::Value::Dict dict; auto entry_or_empty = - [](const absl::optional& entry) -> std::string { + [](const std::optional& entry) -> std::string { return entry.has_value() ? entry->GetDebugString() : "none"; }; @@ -325,10 +324,6 @@ URLRequestHttpJob::URLRequestHttpJob( const HttpUserAgentSettings* http_user_agent_settings) : URLRequestJob(request), http_user_agent_settings_(http_user_agent_settings) { - URLRequestThrottlerManager* manager = request->context()->throttler_manager(); - if (manager) - throttling_entry_ = manager->RegisterRequestUrl(request->url()); - ResetTimer(); } @@ -389,7 +384,7 @@ void URLRequestHttpJob::Start() { request_->net_log().BeginEvent(NetLogEventType::FIRST_PARTY_SETS_METADATA); - absl::optional< + std::optional< std::pair> maybe_metadata = cookie_util::ComputeFirstPartySetMetadataMaybeAsync( SchemefulSite(request()->url()), request()->isolation_info(), @@ -527,9 +522,6 @@ void URLRequestHttpJob::NotifyHeadersComplete() { response_info_ = transaction_->GetResponseInfo(); } - if (!response_info_->was_cached && throttling_entry_.get()) - throttling_entry_->UpdateWithResponse(GetResponseCode()); - ProcessStrictTransportSecurityHeader(); // Clear |set_cookie_access_result_list_| after any processing in case @@ -589,7 +581,7 @@ void URLRequestHttpJob::StartTransaction() { void URLRequestHttpJob::NotifyBeforeStartTransactionCallback( int result, - const absl::optional& headers) { + const std::optional& headers) { // The request should not have been cancelled or have already completed. DCHECK(!is_done()); @@ -668,18 +660,12 @@ void URLRequestHttpJob::StartTransactionInternal() { is_shared_dictionary_read_allowed_callback_); } - if (!throttling_entry_.get() || - !throttling_entry_->ShouldRejectRequest(*request_)) { - rv = transaction_->Start( - &request_info_, - base::BindOnce(&URLRequestHttpJob::OnStartCompleted, - base::Unretained(this)), - request_->net_log()); - start_time_ = base::TimeTicks::Now(); - } else { - // Special error code for the exponential back-off module. - rv = ERR_TEMPORARILY_THROTTLED; - } + rv = transaction_->Start( + &request_info_, + base::BindOnce(&URLRequestHttpJob::OnStartCompleted, + base::Unretained(this)), + request_->net_log()); + start_time_ = base::TimeTicks::Now(); } } @@ -831,7 +817,7 @@ void URLRequestHttpJob::SetCookieHeaderAndStart( if (may_set_sec_cookie_deprecation_header && c.cookie.Name() == "receive-cookie-deprecation" && - c.cookie.IsHttpOnly() && c.cookie.IsSecure()) { + c.cookie.IsHttpOnly() && c.cookie.SecureAttribute()) { request_info_.extra_headers.SetHeader( "Sec-Cookie-Deprecation", *request_->context()->cookie_deprecation_label()); @@ -942,9 +928,9 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { } base::Time response_date; - absl::optional server_time = absl::nullopt; + std::optional server_time = std::nullopt; if (GetResponseHeaders()->GetDateValue(&response_date)) - server_time = absl::make_optional(response_date); + server_time = std::make_optional(response_date); bool force_ignore_site_for_cookies = request_->force_ignore_site_for_cookies(); @@ -998,7 +984,7 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { request_->cookie_partition_key(), /*block_truncated=*/true, &returned_status); - absl::optional cookie_to_return = absl::nullopt; + std::optional cookie_to_return = std::nullopt; if (returned_status.IsInclude()) { DCHECK(cookie); // Make a copy of the cookie if we successfully made one. @@ -1041,11 +1027,10 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) { NotifyHeadersComplete(); } -void URLRequestHttpJob::OnSetCookieResult( - const CookieOptions& options, - absl::optional cookie, - std::string cookie_string, - CookieAccessResult access_result) { +void URLRequestHttpJob::OnSetCookieResult(const CookieOptions& options, + std::optional cookie, + std::string cookie_string, + CookieAccessResult access_result) { if (request_->net_log().IsCapturing()) { request_->net_log().AddEvent(NetLogEventType::COOKIE_INCLUSION_STATUS, [&](NetLogCaptureMode capture_mode) { @@ -1131,7 +1116,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) { // |URLRequestHttpJob::OnHeadersReceivedCallback()| or // |NetworkDelegate::URLRequestDestroyed()| has been called. OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED); - preserve_fragment_on_redirect_url_ = absl::nullopt; + preserve_fragment_on_redirect_url_ = std::nullopt; IPEndPoint endpoint; if (transaction_) transaction_->GetRemoteEndpoint(&endpoint); @@ -1726,16 +1711,16 @@ void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) { return; base::TimeDelta total_time = base::TimeTicks::Now() - start_time_; - UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time); + base::UmaHistogramTimes("Net.HttpJob.TotalTime", total_time); if (reason == FINISHED) { - UmaHistogramTimes( + base::UmaHistogramTimes( base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d", request()->priority()), total_time); - UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time); + base::UmaHistogramTimes("Net.HttpJob.TotalTimeSuccess", total_time); } else { - UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time); + base::UmaHistogramTimes("Net.HttpJob.TotalTimeCancel", total_time); } // These metrics are intended to replace some of the later IP @@ -1760,19 +1745,19 @@ void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) { GetTotalSentBytes() == 0 && GetTotalReceivedBytes() == 0; if (!bypassedNetwork) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.BytesSent2", GetTotalSentBytes(), - 1, 50000000, 50); - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.BytesReceived2", - GetTotalReceivedBytes(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.BytesSent2", + GetTotalSentBytes(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.BytesReceived2", + GetTotalReceivedBytes(), 1, 50000000, 50); // Having a transaction_ does not imply having a response_info_. This is // particularly the case in some aborted/cancelled jobs. The transaction is // the primary source of MDL match information. if ((transaction_ && transaction_->IsMdlMatchForMetrics()) || (response_info_ && response_info_->was_mdl_match)) { - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::UmaHistogramCustomCounts( "Net.HttpJob.IpProtection.AllowListMatch.BytesSent2", GetTotalSentBytes(), 1, 50000000, 50); - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::UmaHistogramCustomCounts( "Net.HttpJob.IpProtection.AllowListMatch.BytesReceived2", GetTotalReceivedBytes(), 1, 50000000, 50); } @@ -1786,8 +1771,8 @@ void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) { bool used_quic = response_info_->DidUseQuic(); if (is_https_google) { if (used_quic) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic", - total_time); + base::UmaHistogramMediumTimes("Net.HttpJob.TotalTime.Secure.Quic", + total_time); } } @@ -1800,45 +1785,54 @@ void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) { base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13.Google", total_time); } - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead", - prefilter_bytes_read(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.PrefilterBytesRead", + prefilter_bytes_read(), 1, 50000000, 50); if (response_info_->was_cached) { - UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time); - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache", - prefilter_bytes_read(), 1, 50000000, 50); + base::UmaHistogramTimes("Net.HttpJob.TotalTimeCached", total_time); + base::UmaHistogramCustomCounts("Net.HttpJob.PrefilterBytesRead.Cache", + prefilter_bytes_read(), 1, 50000000, 50); } else { - UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time); + base::UmaHistogramTimes("Net.HttpJob.TotalTimeNotCached", total_time); if (response_info_->was_mdl_match) { - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::UmaHistogramCustomCounts( "Net.HttpJob.IpProtection.AllowListMatch.BytesSent", GetTotalSentBytes(), 1, 50000000, 50); - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::UmaHistogramCustomCounts( "Net.HttpJob.IpProtection.AllowListMatch.PrefilterBytesRead.Net", prefilter_bytes_read(), 1, 50000000, 50); } - if (response_info_->was_ip_protected) { - UMA_HISTOGRAM_TIMES("Net.HttpJob.IpProtection.TotalTimeNotCached", - total_time); + if (response_info_->proxy_chain.is_for_ip_protection()) { + base::UmaHistogramTimes("Net.HttpJob.IpProtection.TotalTimeNotCached", + total_time); + // Log specific times for non-zero chains. The zero chain is the + // default and is still counted in the base `TotalTimeNotCached`. + int chain_id = response_info_->proxy_chain.ip_protection_chain_id(); + if (chain_id != ProxyChain::kNotIpProtectionChainId) { + UmaHistogramTimes( + base::StrCat({"Net.HttpJob.IpProtection.TotalTimeNotCached.Chain", + base::NumberToString(chain_id)}), + total_time); + } - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.IpProtection.BytesSent", - GetTotalSentBytes(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.IpProtection.BytesSent", + GetTotalSentBytes(), 1, 50000000, 50); - UMA_HISTOGRAM_CUSTOM_COUNTS( + base::UmaHistogramCustomCounts( "Net.HttpJob.IpProtection.PrefilterBytesRead.Net", prefilter_bytes_read(), 1, 50000000, 50); } - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net", - prefilter_bytes_read(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.PrefilterBytesRead.Net", + prefilter_bytes_read(), 1, 50000000, 50); if (request_->ad_tagged()) { - UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Ads.Net", - prefilter_bytes_read(), 1, 50000000, 50); + base::UmaHistogramCustomCounts("Net.HttpJob.PrefilterBytesRead.Ads.Net", + prefilter_bytes_read(), 1, 50000000, 50); } if (is_https_google && used_quic) { - UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTimeNotCached.Secure.Quic", - total_time); + base::UmaHistogramMediumTimes( + "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time); } } } diff --git a/naiveproxy/src/net/url_request/url_request_http_job.h b/naiveproxy/src/net/url_request/url_request_http_job.h index 943ed021a6..34229775cf 100644 --- a/naiveproxy/src/net/url_request/url_request_http_job.h +++ b/naiveproxy/src/net/url_request/url_request_http_job.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -28,8 +29,6 @@ #include "net/http/http_request_info.h" #include "net/socket/connection_attempts.h" #include "net/url_request/url_request_job.h" -#include "net/url_request/url_request_throttler_entry_interface.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -135,7 +134,7 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { void OnReadCompleted(int result); void NotifyBeforeStartTransactionCallback( int result, - const absl::optional& headers); + const std::optional& headers); // This just forwards the call to URLRequestJob::NotifyConnected(). // We need it because that method is protected and cannot be bound in a // callback in this class. @@ -195,7 +194,7 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // Another Cookie Monster callback void OnSetCookieResult(const CookieOptions& options, - absl::optional cookie, + std::optional cookie, std::string cookie_string, CookieAccessResult access_result); int num_cookie_lines_left_ = 0; @@ -251,10 +250,6 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // first. raw_ptr response_info_ = nullptr; - // This is used to supervise traffic and enforce exponential - // back-off. May be NULL. - scoped_refptr throttling_entry_; - base::Time request_creation_time_; // True when we are done doing work. @@ -274,12 +269,12 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob { // Ordinarily the original URL's fragment is copied during redirects, unless // the destination URL already has one. However, the NetworkDelegate can // override this behavior by setting |preserve_fragment_on_redirect_url_|: - // * If set to absl::nullopt, the default behavior is used. + // * If set to std::nullopt, the default behavior is used. // * If the final URL in the redirect chain matches // |preserve_fragment_on_redirect_url_|, its fragment unchanged. So this // is basically a way for the embedder to force a redirect not to copy the // original URL's fragment when the original URL had one. - absl::optional preserve_fragment_on_redirect_url_; + std::optional preserve_fragment_on_redirect_url_; // Flag used to verify that |this| is not deleted while we are awaiting // a callback from the NetworkDelegate. Used as a fail-fast mechanism. diff --git a/naiveproxy/src/net/url_request/url_request_job.cc b/naiveproxy/src/net/url_request/url_request_job.cc index dc6605dc28..e221b9dce7 100644 --- a/naiveproxy/src/net/url_request/url_request_job.cc +++ b/naiveproxy/src/net/url_request/url_request_job.cc @@ -88,9 +88,9 @@ class URLRequestJob::URLRequestJobSourceStream : public SourceStream { URLRequestJob::URLRequestJob(URLRequest* request) : request_(request), request_initiator_site_(request->initiator().has_value() - ? absl::make_optional(net::SchemefulSite( + ? std::make_optional(net::SchemefulSite( request->initiator().value())) - : absl::nullopt) {} + : std::nullopt) {} URLRequestJob::~URLRequestJob() = default; @@ -236,14 +236,14 @@ void URLRequestJob::ContinueDespiteLastError() { } void URLRequestJob::FollowDeferredRedirect( - const absl::optional>& removed_headers, - const absl::optional& modified_headers) { + const std::optional>& removed_headers, + const std::optional& modified_headers) { // OnReceivedRedirect must have been called. DCHECK(deferred_redirect_info_); // It is possible that FollowRedirect will delete |this|, so it is not safe to // pass along a reference to |deferred_redirect_info_|. - absl::optional redirect_info = + std::optional redirect_info = std::move(deferred_redirect_info_); FollowRedirect(*redirect_info, removed_headers, modified_headers); } @@ -469,8 +469,8 @@ void URLRequestJob::NotifyHeadersComplete() { if (defer_redirect) { deferred_redirect_info_ = std::move(redirect_info); } else { - FollowRedirect(redirect_info, absl::nullopt, /* removed_headers */ - absl::nullopt /* modified_headers */); + FollowRedirect(redirect_info, std::nullopt, /* removed_headers */ + std::nullopt /* modified_headers */); } return; } @@ -728,8 +728,8 @@ int URLRequestJob::CanFollowRedirect(const GURL& new_url) { void URLRequestJob::FollowRedirect( const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers) { + const std::optional>& removed_headers, + const std::optional& modified_headers) { request_->Redirect(redirect_info, removed_headers, modified_headers); } diff --git a/naiveproxy/src/net/url_request/url_request_job.h b/naiveproxy/src/net/url_request/url_request_job.h index 4fd599802b..d70c299d1b 100644 --- a/naiveproxy/src/net/url_request/url_request_job.h +++ b/naiveproxy/src/net/url_request/url_request_job.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -30,7 +31,6 @@ #include "net/url_request/redirect_info.h" #include "net/url_request/referrer_policy.h" #include "net/url_request/url_request.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -196,8 +196,8 @@ class NET_EXPORT URLRequestJob { virtual void ContinueDespiteLastError(); void FollowDeferredRedirect( - const absl::optional>& removed_headers, - const absl::optional& modified_headers); + const std::optional>& removed_headers, + const std::optional& modified_headers); // Returns true if the Job is done producing response data and has called // NotifyDone on the request. @@ -360,7 +360,7 @@ class NET_EXPORT URLRequestJob { // On return, |this| may be deleted. void ReadRawDataComplete(int bytes_read); - const absl::optional& request_initiator_site() const { + const std::optional& request_initiator_site() const { return request_initiator_site_; } @@ -390,8 +390,8 @@ class NET_EXPORT URLRequestJob { // given redirect destination. void FollowRedirect( const RedirectInfo& redirect_info, - const absl::optional>& removed_headers, - const absl::optional& modified_headers); + const std::optional>& removed_headers, + const std::optional& modified_headers); // Called after every raw read. If |bytes_read| is > 0, this indicates // a successful read of |bytes_read| unfiltered bytes. If |bytes_read| @@ -448,12 +448,12 @@ class NET_EXPORT URLRequestJob { // Set when a redirect is deferred. Redirects are deferred after validity // checks are performed, so this field must not be modified. - absl::optional deferred_redirect_info_; + std::optional deferred_redirect_info_; // The request's initiator never changes, so we store it in format of // SchemefulSite so that we don't recompute (including looking up the // registrable domain) it during every redirect. - absl::optional request_initiator_site_; + std::optional request_initiator_site_; // Non-null if ReadRawData() returned ERR_IO_PENDING, and the read has not // completed. diff --git a/naiveproxy/src/net/url_request/url_request_netlog_params.cc b/naiveproxy/src/net/url_request/url_request_netlog_params.cc index 323b62f695..6299134a9f 100644 --- a/naiveproxy/src/net/url_request/url_request_netlog_params.cc +++ b/naiveproxy/src/net/url_request/url_request_netlog_params.cc @@ -33,7 +33,7 @@ base::Value::Dict NetLogURLRequestStartParams( int load_flags, const IsolationInfo& isolation_info, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, int64_t upload_id) { base::Value::Dict dict; dict.Set("url", url.possibly_invalid_spec()); diff --git a/naiveproxy/src/net/url_request/url_request_netlog_params.h b/naiveproxy/src/net/url_request/url_request_netlog_params.h index dfb13f4d3e..c11a068f4e 100644 --- a/naiveproxy/src/net/url_request/url_request_netlog_params.h +++ b/naiveproxy/src/net/url_request/url_request_netlog_params.h @@ -8,6 +8,7 @@ #include #include +#include #include #include "base/values.h" @@ -17,7 +18,6 @@ #include "net/base/request_priority.h" #include "net/log/net_log_capture_mode.h" #include "net/traffic_annotation/network_traffic_annotation.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -42,7 +42,7 @@ NET_EXPORT base::Value::Dict NetLogURLRequestStartParams( int load_flags, const IsolationInfo& isolation_info, const SiteForCookies& site_for_cookies, - const absl::optional& initiator, + const std::optional& initiator, int64_t upload_id); } // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_test_util.cc b/naiveproxy/src/net/url_request/url_request_test_util.cc index 297905bdc9..e025824b74 100644 --- a/naiveproxy/src/net/url_request/url_request_test_util.cc +++ b/naiveproxy/src/net/url_request/url_request_test_util.cc @@ -357,7 +357,7 @@ int TestNetworkDelegate::OnHeadersReceived( const HttpResponseHeaders* original_response_headers, scoped_refptr* override_response_headers, const IPEndPoint& endpoint, - absl::optional* preserve_fragment_on_redirect_url) { + std::optional* preserve_fragment_on_redirect_url) { EXPECT_FALSE(preserve_fragment_on_redirect_url->has_value()); int req_id = GetRequestId(request); bool is_first_response = @@ -385,7 +385,7 @@ int TestNetworkDelegate::OnHeadersReceived( redirect_on_headers_received_url_ = GURL(); - // Since both values are absl::optionals, can just copy this over. + // Since both values are std::optionals, can just copy this over. *preserve_fragment_on_redirect_url = preserve_fragment_on_redirect_url_; } else if (add_header_to_first_response_ && is_first_response) { *override_response_headers = base::MakeRefCounted( diff --git a/naiveproxy/src/net/url_request/url_request_test_util.h b/naiveproxy/src/net/url_request/url_request_test_util.h index 0fdcd605a0..575a510b7e 100644 --- a/naiveproxy/src/net/url_request/url_request_test_util.h +++ b/naiveproxy/src/net/url_request/url_request_test_util.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -47,7 +48,6 @@ #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_interceptor.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/url_util.h" namespace net { @@ -251,7 +251,7 @@ class TestNetworkDelegate : public NetworkDelegateImpl { } void set_preserve_fragment_on_redirect_url( - const absl::optional& preserve_fragment_on_redirect_url) { + const std::optional& preserve_fragment_on_redirect_url) { preserve_fragment_on_redirect_url_ = preserve_fragment_on_redirect_url; } @@ -303,7 +303,7 @@ class TestNetworkDelegate : public NetworkDelegateImpl { const HttpResponseHeaders* original_response_headers, scoped_refptr* override_response_headers, const IPEndPoint& endpoint, - absl::optional* preserve_fragment_on_redirect_url) override; + std::optional* preserve_fragment_on_redirect_url) override; void OnBeforeRedirect(URLRequest* request, const GURL& new_location) override; void OnResponseStarted(URLRequest* request, int net_error) override; void OnCompleted(URLRequest* request, bool started, int net_error) override; @@ -339,7 +339,7 @@ class TestNetworkDelegate : public NetworkDelegateImpl { GURL redirect_on_headers_received_url_; // URL to mark as retaining its fragment if redirected to at the // OnHeadersReceived() stage. - absl::optional preserve_fragment_on_redirect_url_; + std::optional preserve_fragment_on_redirect_url_; int last_error_ = 0; int error_count_ = 0; diff --git a/naiveproxy/src/net/url_request/url_request_throttler_entry.cc b/naiveproxy/src/net/url_request/url_request_throttler_entry.cc deleted file mode 100644 index 7065bc6ca0..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_entry.cc +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/url_request/url_request_throttler_entry.h" - -#include -#include - -#include "base/check_op.h" -#include "base/functional/bind.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/histogram_macros.h" -#include "base/rand_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/values.h" -#include "net/base/load_flags.h" -#include "net/log/net_log_capture_mode.h" -#include "net/log/net_log_event_type.h" -#include "net/log/net_log_source_type.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_throttler_manager.h" - -namespace net { - -const int URLRequestThrottlerEntry::kDefaultSlidingWindowPeriodMs = 2000; -const int URLRequestThrottlerEntry::kDefaultMaxSendThreshold = 20; - -// This set of back-off parameters will (at maximum values, i.e. without -// the reduction caused by jitter) add 0-41% (distributed uniformly -// in that range) to the "perceived downtime" of the remote server, once -// exponential back-off kicks in and is throttling requests for more than -// about a second at a time. Once the maximum back-off is reached, the added -// perceived downtime decreases rapidly, percentage-wise. -// -// Another way to put it is that the maximum additional perceived downtime -// with these numbers is a couple of seconds shy of 15 minutes, and such -// a delay would not occur until the remote server has been actually -// unavailable at the end of each back-off period for a total of about -// 48 minutes. -// -// Ignoring the first couple of errors is just a conservative measure to -// avoid false positives. It should help avoid back-off from kicking in e.g. -// on flaky connections. -const int URLRequestThrottlerEntry::kDefaultNumErrorsToIgnore = 2; -const int URLRequestThrottlerEntry::kDefaultInitialDelayMs = 700; -const double URLRequestThrottlerEntry::kDefaultMultiplyFactor = 1.4; -const double URLRequestThrottlerEntry::kDefaultJitterFactor = 0.4; -const int URLRequestThrottlerEntry::kDefaultMaximumBackoffMs = 15 * 60 * 1000; -const int URLRequestThrottlerEntry::kDefaultEntryLifetimeMs = 2 * 60 * 1000; - -// Returns NetLog parameters when a request is rejected by throttling. -base::Value::Dict NetLogRejectedRequestParams( - const std::string* url_id, - int num_failures, - const base::TimeDelta& release_after) { - base::Value::Dict dict; - dict.Set("url", *url_id); - dict.Set("num_failures", num_failures); - dict.Set("release_after_ms", - static_cast(release_after.InMilliseconds())); - return dict; -} - -URLRequestThrottlerEntry::URLRequestThrottlerEntry( - URLRequestThrottlerManager* manager, - const std::string& url_id) - : sliding_window_period_(base::Milliseconds(kDefaultSlidingWindowPeriodMs)), - max_send_threshold_(kDefaultMaxSendThreshold), - backoff_entry_(&backoff_policy_), - manager_(manager), - url_id_(url_id), - net_log_(NetLogWithSource::Make( - manager->net_log(), - NetLogSourceType::EXPONENTIAL_BACKOFF_THROTTLING)) { - DCHECK(manager_); - Initialize(); -} - -URLRequestThrottlerEntry::URLRequestThrottlerEntry( - URLRequestThrottlerManager* manager, - const std::string& url_id, - int sliding_window_period_ms, - int max_send_threshold, - int initial_backoff_ms, - double multiply_factor, - double jitter_factor, - int maximum_backoff_ms) - : sliding_window_period_(base::Milliseconds(sliding_window_period_ms)), - max_send_threshold_(max_send_threshold), - backoff_entry_(&backoff_policy_), - manager_(manager), - url_id_(url_id) { - DCHECK_GT(sliding_window_period_ms, 0); - DCHECK_GT(max_send_threshold_, 0); - DCHECK_GE(initial_backoff_ms, 0); - DCHECK_GT(multiply_factor, 0); - DCHECK_GE(jitter_factor, 0.0); - DCHECK_LT(jitter_factor, 1.0); - DCHECK_GE(maximum_backoff_ms, 0); - DCHECK(manager_); - - Initialize(); - backoff_policy_.initial_delay_ms = initial_backoff_ms; - backoff_policy_.multiply_factor = multiply_factor; - backoff_policy_.jitter_factor = jitter_factor; - backoff_policy_.maximum_backoff_ms = maximum_backoff_ms; - backoff_policy_.entry_lifetime_ms = -1; - backoff_policy_.num_errors_to_ignore = 0; - backoff_policy_.always_use_initial_delay = false; -} - -bool URLRequestThrottlerEntry::IsEntryOutdated() const { - // This function is called by the URLRequestThrottlerManager to determine - // whether entries should be discarded from its url_entries_ map. We - // want to ensure that it does not remove entries from the map while there - // are clients (objects other than the manager) holding references to - // the entry, otherwise separate clients could end up holding separate - // entries for a request to the same URL, which is undesirable. Therefore, - // if an entry has more than one reference (the map will always hold one), - // it should not be considered outdated. - // - // We considered whether to make URLRequestThrottlerEntry objects - // non-refcounted, but since any means of knowing whether they are - // currently in use by others than the manager would be more or less - // equivalent to a refcount, we kept them refcounted. - if (!HasOneRef()) - return false; - - // If there are send events in the sliding window period, we still need this - // entry. - if (!send_log_.empty() && - send_log_.back() + sliding_window_period_ > ImplGetTimeNow()) { - return false; - } - - return GetBackoffEntry()->CanDiscard(); -} - -void URLRequestThrottlerEntry::DisableBackoffThrottling() { - is_backoff_disabled_ = true; -} - -void URLRequestThrottlerEntry::DetachManager() { - manager_ = nullptr; -} - -bool URLRequestThrottlerEntry::ShouldRejectRequest( - const URLRequest& request) const { - bool reject_request = false; - if (!is_backoff_disabled_ && GetBackoffEntry()->ShouldRejectRequest()) { - net_log_.AddEvent(NetLogEventType::THROTTLING_REJECTED_REQUEST, [&] { - return NetLogRejectedRequestParams( - &url_id_, GetBackoffEntry()->failure_count(), - GetBackoffEntry()->GetTimeUntilRelease()); - }); - reject_request = true; - } - - int reject_count = reject_request ? 1 : 0; - UMA_HISTOGRAM_ENUMERATION( - "Throttling.RequestThrottled", reject_count, 2); - - return reject_request; -} - -int64_t URLRequestThrottlerEntry::ReserveSendingTimeForNextRequest( - const base::TimeTicks& earliest_time) { - base::TimeTicks now = ImplGetTimeNow(); - - // If a lot of requests were successfully made recently, - // sliding_window_release_time_ may be greater than - // exponential_backoff_release_time_. - base::TimeTicks recommended_sending_time = - std::max(std::max(now, earliest_time), - std::max(GetBackoffEntry()->GetReleaseTime(), - sliding_window_release_time_)); - - DCHECK(send_log_.empty() || - recommended_sending_time >= send_log_.back()); - // Log the new send event. - send_log_.push(recommended_sending_time); - - sliding_window_release_time_ = recommended_sending_time; - - // Drop the out-of-date events in the event list. - // We don't need to worry that the queue may become empty during this - // operation, since the last element is sliding_window_release_time_. - while ((send_log_.front() + sliding_window_period_ <= - sliding_window_release_time_) || - send_log_.size() > static_cast(max_send_threshold_)) { - send_log_.pop(); - } - - // Check if there are too many send events in recent time. - if (send_log_.size() == static_cast(max_send_threshold_)) - sliding_window_release_time_ = send_log_.front() + sliding_window_period_; - - return (recommended_sending_time - now).InMillisecondsRoundedUp(); -} - -base::TimeTicks - URLRequestThrottlerEntry::GetExponentialBackoffReleaseTime() const { - // If a site opts out, it's likely because they have problems that trigger - // the back-off mechanism when it shouldn't be triggered, in which case - // returning the calculated back-off release time would probably be the - // wrong thing to do (i.e. it would likely be too long). Therefore, we - // return "now" so that retries are not delayed. - if (is_backoff_disabled_) - return ImplGetTimeNow(); - - return GetBackoffEntry()->GetReleaseTime(); -} - -void URLRequestThrottlerEntry::UpdateWithResponse(int status_code) { - GetBackoffEntry()->InformOfRequest(IsConsideredSuccess(status_code)); -} - -void URLRequestThrottlerEntry::ReceivedContentWasMalformed(int response_code) { - // A malformed body can only occur when the request to fetch a resource - // was successful. Therefore, in such a situation, we will receive one - // call to ReceivedContentWasMalformed() and one call to - // UpdateWithResponse() with a response categorized as "good". To end - // up counting one failure, we need to count two failures here against - // the one success in UpdateWithResponse(). - // - // We do nothing for a response that is already being considered an error - // based on its status code (otherwise we would count 3 errors instead of 1). - if (IsConsideredSuccess(response_code)) { - GetBackoffEntry()->InformOfRequest(false); - GetBackoffEntry()->InformOfRequest(false); - } -} - -URLRequestThrottlerEntry::~URLRequestThrottlerEntry() = default; - -void URLRequestThrottlerEntry::Initialize() { - sliding_window_release_time_ = base::TimeTicks::Now(); - backoff_policy_.num_errors_to_ignore = kDefaultNumErrorsToIgnore; - backoff_policy_.initial_delay_ms = kDefaultInitialDelayMs; - backoff_policy_.multiply_factor = kDefaultMultiplyFactor; - backoff_policy_.jitter_factor = kDefaultJitterFactor; - backoff_policy_.maximum_backoff_ms = kDefaultMaximumBackoffMs; - backoff_policy_.entry_lifetime_ms = kDefaultEntryLifetimeMs; - backoff_policy_.always_use_initial_delay = false; -} - -bool URLRequestThrottlerEntry::IsConsideredSuccess(int response_code) { - // We throttle only for the status codes most likely to indicate the server - // is failing because it is too busy or otherwise are likely to be - // because of DDoS. - // - // 500 is the generic error when no better message is suitable, and - // as such does not necessarily indicate a temporary state, but - // other status codes cover most of the permanent error states. - // 503 is explicitly documented as a temporary state where the server - // is either overloaded or down for maintenance. - // 509 is the (non-standard but widely implemented) Bandwidth Limit Exceeded - // status code, which might indicate DDoS. - // - // We do not back off on 502 or 504, which are reported by gateways - // (proxies) on timeouts or failures, because in many cases these requests - // have not made it to the destination server and so we do not actually - // know that it is down or busy. One degenerate case could be a proxy on - // localhost, where you are not actually connected to the network. - return !(response_code == 500 || response_code == 503 || - response_code == 509); -} - -base::TimeTicks URLRequestThrottlerEntry::ImplGetTimeNow() const { - return base::TimeTicks::Now(); -} - -const BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() const { - return &backoff_entry_; -} - -BackoffEntry* URLRequestThrottlerEntry::GetBackoffEntry() { - return &backoff_entry_; -} - -} // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_throttler_entry.h b/naiveproxy/src/net/url_request/url_request_throttler_entry.h deleted file mode 100644 index b08e5decb7..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_entry.h +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_H_ -#define NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_H_ - -#include - -#include - -#include "base/containers/queue.h" -#include "base/memory/raw_ptr.h" -#include "base/time/time.h" -#include "net/base/backoff_entry.h" -#include "net/base/net_export.h" -#include "net/log/net_log_with_source.h" -#include "net/url_request/url_request_throttler_entry_interface.h" - -namespace net { - -class URLRequestThrottlerManager; - -// URLRequestThrottlerEntry represents an entry of URLRequestThrottlerManager. -// It analyzes requests of a specific URL over some period of time, in order to -// deduce the back-off time for every request. -// The back-off algorithm consists of two parts. Firstly, exponential back-off -// is used when receiving 5XX server errors or malformed response bodies. -// The exponential back-off rule is enforced by URLRequestHttpJob. Any -// request sent during the back-off period will be cancelled. -// Secondly, a sliding window is used to count recent requests to a given -// destination and provide guidance (to the application level only) on whether -// too many requests have been sent and when a good time to send the next one -// would be. This is never used to deny requests at the network level. -class NET_EXPORT URLRequestThrottlerEntry - : public URLRequestThrottlerEntryInterface { - public: - // Sliding window period. - static const int kDefaultSlidingWindowPeriodMs; - - // Maximum number of requests allowed in sliding window period. - static const int kDefaultMaxSendThreshold; - - // Number of initial errors to ignore before starting exponential back-off. - static const int kDefaultNumErrorsToIgnore; - - // Initial delay for exponential back-off. - static const int kDefaultInitialDelayMs; - - // Factor by which the waiting time will be multiplied. - static const double kDefaultMultiplyFactor; - - // Fuzzing percentage. ex: 10% will spread requests randomly - // between 90%-100% of the calculated time. - static const double kDefaultJitterFactor; - - // Maximum amount of time we are willing to delay our request. - static const int kDefaultMaximumBackoffMs; - - // Time after which the entry is considered outdated. - static const int kDefaultEntryLifetimeMs; - - // The manager object's lifetime must enclose the lifetime of this object. - URLRequestThrottlerEntry(URLRequestThrottlerManager* manager, - const std::string& url_id); - - // The life span of instances created with this constructor is set to - // infinite, and the number of initial errors to ignore is set to 0. - // It is only used by unit tests. - URLRequestThrottlerEntry(URLRequestThrottlerManager* manager, - const std::string& url_id, - int sliding_window_period_ms, - int max_send_threshold, - int initial_backoff_ms, - double multiply_factor, - double jitter_factor, - int maximum_backoff_ms); - - URLRequestThrottlerEntry(const URLRequestThrottlerEntry&) = delete; - URLRequestThrottlerEntry& operator=(const URLRequestThrottlerEntry&) = delete; - - // Used by the manager, returns true if the entry needs to be garbage - // collected. - bool IsEntryOutdated() const; - - // Causes this entry to never reject requests due to back-off. - void DisableBackoffThrottling(); - - // Causes this entry to NULL its manager pointer. - void DetachManager(); - - // Implementation of URLRequestThrottlerEntryInterface. - bool ShouldRejectRequest(const URLRequest& request) const override; - int64_t ReserveSendingTimeForNextRequest( - const base::TimeTicks& earliest_time) override; - base::TimeTicks GetExponentialBackoffReleaseTime() const override; - void UpdateWithResponse(int status_code) override; - void ReceivedContentWasMalformed(int response_code) override; - - protected: - ~URLRequestThrottlerEntry() override; - - void Initialize(); - - // Returns true if the given response code is considered a success for - // throttling purposes. - bool IsConsideredSuccess(int response_code); - - // Equivalent to TimeTicks::Now(), virtual to be mockable for testing purpose. - virtual base::TimeTicks ImplGetTimeNow() const; - - // Retrieves the back-off entry object we're using. Used to enable a - // unit testing seam for dependency injection in tests. - virtual const BackoffEntry* GetBackoffEntry() const; - virtual BackoffEntry* GetBackoffEntry(); - - // Used by tests. - base::TimeTicks sliding_window_release_time() const { - return sliding_window_release_time_; - } - - // Used by tests. - void set_sliding_window_release_time(const base::TimeTicks& release_time) { - sliding_window_release_time_ = release_time; - } - - // Valid and immutable after construction time. - BackoffEntry::Policy backoff_policy_; - - private: - // Timestamp calculated by the sliding window algorithm for when we advise - // clients the next request should be made, at the earliest. Advisory only, - // not used to deny requests. - base::TimeTicks sliding_window_release_time_; - - // A list of the recent send events. We use them to decide whether there are - // too many requests sent in sliding window. - base::queue send_log_; - - const base::TimeDelta sliding_window_period_; - const int max_send_threshold_; - - // True if DisableBackoffThrottling() has been called on this object. - bool is_backoff_disabled_ = false; - - // Access it through GetBackoffEntry() to allow a unit test seam. - BackoffEntry backoff_entry_; - - // Weak back-reference to the manager object managing us. - raw_ptr manager_; - - // Canonicalized URL string that this entry is for; used for logging only. - std::string url_id_; - - NetLogWithSource net_log_; -}; - -} // namespace net - -#endif // NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_H_ diff --git a/naiveproxy/src/net/url_request/url_request_throttler_entry_interface.h b/naiveproxy/src/net/url_request/url_request_throttler_entry_interface.h deleted file mode 100644 index c9e7ca728a..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_entry_interface.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_INTERFACE_H_ -#define NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_INTERFACE_H_ - -#include - -#include "base/memory/ref_counted.h" -#include "base/time/time.h" -#include "net/base/net_export.h" - -namespace net { - -class URLRequest; - -// Interface provided on entries of the URL request throttler manager. -class NET_EXPORT URLRequestThrottlerEntryInterface - : public base::RefCountedThreadSafe { - public: - URLRequestThrottlerEntryInterface() = default; - - URLRequestThrottlerEntryInterface(const URLRequestThrottlerEntryInterface&) = - delete; - URLRequestThrottlerEntryInterface& operator=( - const URLRequestThrottlerEntryInterface&) = delete; - - // Returns true when we have encountered server errors and are doing - // exponential back-off, unless the request has load flags that mean - // it is likely to be user-initiated. - // - // URLRequestHttpJob checks this method prior to every request; it - // cancels requests if this method returns true. - virtual bool ShouldRejectRequest(const URLRequest& request) const = 0; - - // Calculates a recommended sending time for the next request and reserves it. - // The sending time is not earlier than the current exponential back-off - // release time or |earliest_time|. Moreover, the previous results of - // the method are taken into account, in order to make sure they are spread - // properly over time. - // Returns the recommended delay before sending the next request, in - // milliseconds. The return value is always positive or 0. - // Although it is not mandatory, respecting the value returned by this method - // is helpful to avoid traffic overload. - virtual int64_t ReserveSendingTimeForNextRequest( - const base::TimeTicks& earliest_time) = 0; - - // Returns the time after which requests are allowed. - virtual base::TimeTicks GetExponentialBackoffReleaseTime() const = 0; - - // This method needs to be called each time a response is received. - virtual void UpdateWithResponse(int status_code) = 0; - - // Lets higher-level modules, that know how to parse particular response - // bodies, notify of receiving malformed content for the given URL. This will - // be handled by the throttler as if an HTTP 503 response had been received to - // the request, i.e. it will count as a failure, unless the HTTP response code - // indicated is already one of those that will be counted as an error. - virtual void ReceivedContentWasMalformed(int response_code) = 0; - - protected: - friend class base::RefCountedThreadSafe; - virtual ~URLRequestThrottlerEntryInterface() = default; - - private: - friend class base::RefCounted; -}; - -} // namespace net - -#endif // NET_URL_REQUEST_URL_REQUEST_THROTTLER_ENTRY_INTERFACE_H_ diff --git a/naiveproxy/src/net/url_request/url_request_throttler_manager.cc b/naiveproxy/src/net/url_request/url_request_throttler_manager.cc deleted file mode 100644 index a535e3202a..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_manager.cc +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/url_request/url_request_throttler_manager.h" - -#include "base/check_op.h" -#include "base/strings/string_util.h" -#include "net/base/url_util.h" -#include "net/log/net_log.h" -#include "net/log/net_log_event_type.h" -#include "net/log/net_log_source_type.h" - -namespace net { - -const unsigned int URLRequestThrottlerManager::kMaximumNumberOfEntries = 1500; -const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200; - -URLRequestThrottlerManager::URLRequestThrottlerManager() { - url_id_replacements_.ClearPassword(); - url_id_replacements_.ClearUsername(); - url_id_replacements_.ClearQuery(); - url_id_replacements_.ClearRef(); - - NetworkChangeNotifier::AddIPAddressObserver(this); - NetworkChangeNotifier::AddConnectionTypeObserver(this); -} - -URLRequestThrottlerManager::~URLRequestThrottlerManager() { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - NetworkChangeNotifier::RemoveIPAddressObserver(this); - NetworkChangeNotifier::RemoveConnectionTypeObserver(this); - - // Since the manager object might conceivably go away before the - // entries, detach the entries' back-pointer to the manager. - auto i = url_entries_.begin(); - while (i != url_entries_.end()) { - if (i->second.get() != nullptr) { - i->second->DetachManager(); - } - ++i; - } - - // Delete all entries. - url_entries_.clear(); -} - -scoped_refptr - URLRequestThrottlerManager::RegisterRequestUrl(const GURL &url) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - - // Normalize the url. - std::string url_id = GetIdFromUrl(url); - - // Periodically garbage collect old entries. - GarbageCollectEntriesIfNecessary(); - - // Find the entry in the map or create a new NULL entry. - scoped_refptr& entry = url_entries_[url_id]; - - // If the entry exists but could be garbage collected at this point, we - // start with a fresh entry so that we possibly back off a bit less - // aggressively (i.e. this resets the error count when the entry's URL - // hasn't been requested in long enough). - if (entry.get() && entry->IsEntryOutdated()) { - entry = nullptr; - } - - // Create the entry if needed. - if (entry.get() == nullptr) { - entry = base::MakeRefCounted(this, url_id); - - // We only disable back-off throttling on an entry that we have - // just constructed. This is to allow unit tests to explicitly override - // the entry for localhost URLs. - if (IsLocalhost(url)) { - if (!logged_for_localhost_disabled_ && IsLocalhost(url)) { - logged_for_localhost_disabled_ = true; - net_log_.AddEventWithStringParams( - NetLogEventType::THROTTLING_DISABLED_FOR_HOST, "host", url.host()); - } - - // TODO(joi): Once sliding window is separate from back-off throttling, - // we can simply return a dummy implementation of - // URLRequestThrottlerEntryInterface here that never blocks anything. - entry->DisableBackoffThrottling(); - } - } - - return entry; -} - -void URLRequestThrottlerManager::OverrideEntryForTests( - const GURL& url, - scoped_refptr entry) { - // Normalize the url. - std::string url_id = GetIdFromUrl(url); - - // Periodically garbage collect old entries. - GarbageCollectEntriesIfNecessary(); - - url_entries_[url_id] = std::move(entry); -} - -void URLRequestThrottlerManager::EraseEntryForTests(const GURL& url) { - // Normalize the url. - std::string url_id = GetIdFromUrl(url); - url_entries_.erase(url_id); -} - -void URLRequestThrottlerManager::set_net_log(NetLog* net_log) { - DCHECK(net_log); - net_log_ = NetLogWithSource::Make( - net_log, NetLogSourceType::EXPONENTIAL_BACKOFF_THROTTLING); -} - -NetLog* URLRequestThrottlerManager::net_log() const { - return net_log_.net_log(); -} - -void URLRequestThrottlerManager::OnIPAddressChanged() { - OnNetworkChange(); -} - -void URLRequestThrottlerManager::OnConnectionTypeChanged( - NetworkChangeNotifier::ConnectionType type) { - OnNetworkChange(); -} - -std::string URLRequestThrottlerManager::GetIdFromUrl(const GURL& url) const { - if (!url.is_valid()) - return url.possibly_invalid_spec(); - - GURL id = url.ReplaceComponents(url_id_replacements_); - return base::ToLowerASCII(id.spec()); -} - -void URLRequestThrottlerManager::GarbageCollectEntriesIfNecessary() { - requests_since_last_gc_++; - if (requests_since_last_gc_ < kRequestsBetweenCollecting) - return; - requests_since_last_gc_ = 0; - - GarbageCollectEntries(); -} - -void URLRequestThrottlerManager::GarbageCollectEntries() { - auto i = url_entries_.begin(); - while (i != url_entries_.end()) { - if ((i->second)->IsEntryOutdated()) { - url_entries_.erase(i++); - } else { - ++i; - } - } - - // In case something broke we want to make sure not to grow indefinitely. - while (url_entries_.size() > kMaximumNumberOfEntries) { - url_entries_.erase(url_entries_.begin()); - } -} - -void URLRequestThrottlerManager::OnNetworkChange() { - // Remove all entries. Any entries that in-flight requests have a reference - // to will live until those requests end, and these entries may be - // inconsistent with new entries for the same URLs, but since what we - // want is a clean slate for the new connection type, this is OK. - url_entries_.clear(); - requests_since_last_gc_ = 0; -} - -} // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_throttler_manager.h b/naiveproxy/src/net/url_request/url_request_throttler_manager.h deleted file mode 100644 index 139ba8db00..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_manager.h +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_URL_REQUEST_URL_REQUEST_THROTTLER_MANAGER_H_ -#define NET_URL_REQUEST_URL_REQUEST_THROTTLER_MANAGER_H_ - -#include -#include -#include - -#include "base/memory/scoped_refptr.h" -#include "base/threading/platform_thread.h" -#include "base/threading/thread_checker.h" -#include "net/base/net_export.h" -#include "net/base/network_change_notifier.h" -#include "net/url_request/url_request_throttler_entry.h" -#include "url/gurl.h" - -namespace net { - -class NetLog; -class NetLogWithSource; - -// Class that registers URL request throttler entries for URLs being accessed -// in order to supervise traffic. URL requests for HTTP contents should -// register their URLs in this manager on each request. -// -// URLRequestThrottlerManager maintains a map of URL IDs to URL request -// throttler entries. It creates URL request throttler entries when new URLs -// are registered, and does garbage collection from time to time in order to -// clean out outdated entries. URL ID consists of lowercased scheme, host, port -// and path. All URLs converted to the same ID will share the same entry. -class NET_EXPORT_PRIVATE URLRequestThrottlerManager - : public NetworkChangeNotifier::IPAddressObserver, - public NetworkChangeNotifier::ConnectionTypeObserver { - public: - URLRequestThrottlerManager(); - - URLRequestThrottlerManager(const URLRequestThrottlerManager&) = delete; - URLRequestThrottlerManager& operator=(const URLRequestThrottlerManager&) = - delete; - - ~URLRequestThrottlerManager() override; - - // Must be called for every request, returns the URL request throttler entry - // associated with the URL. The caller must inform this entry of some events. - // Please refer to url_request_throttler_entry_interface.h for further - // informations. - scoped_refptr RegisterRequestUrl( - const GURL& url); - - // Registers a new entry in this service and overrides the existing entry (if - // any) for the URL. The service will hold a reference to the entry. - // It is only used by unit tests. - void OverrideEntryForTests(const GURL& url, - scoped_refptr entry); - - // Explicitly erases an entry. - // This is useful to remove those entries which have got infinite lifetime and - // thus won't be garbage collected. - // It is only used by unit tests. - void EraseEntryForTests(const GURL& url); - - // Whether throttling is enabled or not. - void set_enforce_throttling(bool enforce); - bool enforce_throttling(); - - // Sets the NetLog instance to use. - void set_net_log(NetLog* net_log); - NetLog* net_log() const; - - // IPAddressObserver interface. - void OnIPAddressChanged() override; - - // ConnectionTypeObserver interface. - void OnConnectionTypeChanged( - NetworkChangeNotifier::ConnectionType type) override; - - // Method that allows us to transform a URL into an ID that can be used in our - // map. Resulting IDs will be lowercase and consist of the scheme, host, port - // and path (without query string, fragment, etc.). - // If the URL is invalid, the invalid spec will be returned, without any - // transformation. - std::string GetIdFromUrl(const GURL& url) const; - - // Method that ensures the map gets cleaned from time to time. The period at - // which garbage collecting happens is adjustable with the - // kRequestBetweenCollecting constant. - void GarbageCollectEntriesIfNecessary(); - - // Method that does the actual work of garbage collecting. - void GarbageCollectEntries(); - - // When we switch from online to offline or change IP addresses, we - // clear all back-off history. This is a precaution in case the change in - // online state now lets us communicate without error with servers that - // we were previously getting 500 or 503 responses from (perhaps the - // responses are from a badly-written proxy that should have returned a - // 502 or 504 because it's upstream connection was down or it had no route - // to the server). - void OnNetworkChange(); - - // Used by tests. - int GetNumberOfEntriesForTests() const { - return static_cast(url_entries_.size()); - } - - private: - // From each URL we generate an ID composed of the scheme, host, port and path - // that allows us to uniquely map an entry to it. - typedef std::map > - UrlEntryMap; - - // Maximum number of entries that we are willing to collect in our map. - static const unsigned int kMaximumNumberOfEntries; - // Number of requests that will be made between garbage collection. - static const unsigned int kRequestsBetweenCollecting; - - // Map that contains a list of URL ID and their matching - // URLRequestThrottlerEntry. - UrlEntryMap url_entries_; - - // This keeps track of how many requests have been made. Used with - // GarbageCollectEntries. - unsigned int requests_since_last_gc_ = 0; - - // Valid after construction. - GURL::Replacements url_id_replacements_; - - // Certain tests do not obey the net component's threading policy, so we - // keep track of whether we're being used by tests, and turn off certain - // checks. - // - // TODO(joi): See if we can fix the offending unit tests and remove this - // workaround. - bool enable_thread_checks_; - - // Initially false, switches to true once we have logged because of back-off - // being disabled for localhost. - bool logged_for_localhost_disabled_ = false; - - // NetLog to use, if configured. - NetLogWithSource net_log_; - - // Valid once we've registered for network notifications. - base::PlatformThreadId registered_from_thread_ = base::kInvalidThreadId; - - THREAD_CHECKER(thread_checker_); -}; - -} // namespace net - -#endif // NET_URL_REQUEST_URL_REQUEST_THROTTLER_MANAGER_H_ diff --git a/naiveproxy/src/net/url_request/url_request_throttler_test_support.cc b/naiveproxy/src/net/url_request/url_request_throttler_test_support.cc deleted file mode 100644 index a8915a4b18..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_test_support.cc +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "net/url_request/url_request_throttler_test_support.h" - -#include "net/url_request/url_request_throttler_entry.h" - -namespace net { - -TestTickClock::TestTickClock() = default; - -TestTickClock::TestTickClock(base::TimeTicks now) : now_ticks_(now) {} - -TestTickClock::~TestTickClock() = default; - -base::TimeTicks TestTickClock::NowTicks() const { - return now_ticks_; -} - -} // namespace net diff --git a/naiveproxy/src/net/url_request/url_request_throttler_test_support.h b/naiveproxy/src/net/url_request/url_request_throttler_test_support.h deleted file mode 100644 index b620db691e..0000000000 --- a/naiveproxy/src/net/url_request/url_request_throttler_test_support.h +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef NET_URL_REQUEST_URL_REQUEST_THROTTLER_TEST_SUPPORT_H_ -#define NET_URL_REQUEST_URL_REQUEST_THROTTLER_TEST_SUPPORT_H_ - -#include "base/time/tick_clock.h" -#include "base/time/time.h" -#include "net/base/backoff_entry.h" - -namespace net { - -class TestTickClock : public base::TickClock { - public: - TestTickClock(); - explicit TestTickClock(base::TimeTicks now); - - TestTickClock(const TestTickClock&) = delete; - TestTickClock& operator=(const TestTickClock&) = delete; - - ~TestTickClock() override; - - base::TimeTicks NowTicks() const override; - void set_now(base::TimeTicks now) { now_ticks_ = now; } - - private: - base::TimeTicks now_ticks_; -}; - -} // namespace net - -#endif // NET_URL_REQUEST_URL_REQUEST_THROTTLER_TEST_SUPPORT_H_ diff --git a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc index 8c3fc76116..854aa2a83d 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.cc @@ -491,7 +491,7 @@ int WebSocketBasicHandshakeStream::ValidateResponse(int rv) { // helpful, so use a different error message. if (headers->GetHttpVersion() == HttpVersion(0, 9)) { OnFailure("Error during WebSocket handshake: Invalid status line", - ERR_FAILED, absl::nullopt); + ERR_FAILED, std::nullopt); } else { OnFailure(base::StringPrintf("Error during WebSocket handshake: " "Unexpected response code: %d", @@ -504,13 +504,13 @@ int WebSocketBasicHandshakeStream::ValidateResponse(int rv) { } else { if (rv == ERR_EMPTY_RESPONSE) { OnFailure("Connection closed before receiving a handshake response", rv, - absl::nullopt); + std::nullopt); result_ = HandshakeResult::EMPTY_RESPONSE; return rv; } OnFailure( base::StrCat({"Error during WebSocket handshake: ", ErrorToString(rv)}), - rv, absl::nullopt); + rv, std::nullopt); // Some error codes (for example ERR_CONNECTION_CLOSED) get changed to OK at // higher levels. To prevent an unvalidated connection getting erroneously // upgraded, don't pass through the status code unchanged if it is @@ -550,14 +550,14 @@ int WebSocketBasicHandshakeStream::ValidateUpgradeResponse( return OK; } OnFailure("Error during WebSocket handshake: " + failure_message, ERR_FAILED, - absl::nullopt); + std::nullopt); return ERR_INVALID_RESPONSE; } void WebSocketBasicHandshakeStream::OnFailure( const std::string& message, int net_error, - absl::optional response_code) { + std::optional response_code) { net_log_.AddEvent(net::NetLogEventType::WEBSOCKET_UPGRADE_FAILURE, [&] { return NetLogFailureParam(net_error, message); }); // Avoid connection reuse if auth did not happen. diff --git a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h index dbde35e244..8665e25257 100644 --- a/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_basic_handshake_stream.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -22,7 +23,6 @@ #include "net/log/net_log_with_source.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace net { @@ -127,7 +127,7 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream final void OnFailure(const std::string& message, int net_error, - absl::optional response_code); + std::optional response_code); HttpStreamParser* parser() const { return state_.parser(); } @@ -149,7 +149,7 @@ class NET_EXPORT_PRIVATE WebSocketBasicHandshakeStream final // The key to be sent in the next Sec-WebSocket-Key header. Usually NULL (the // key is generated on the fly). - absl::optional handshake_challenge_for_testing_; + std::optional handshake_challenge_for_testing_; // The required value for the Sec-WebSocket-Accept header. std::string handshake_challenge_response_; diff --git a/naiveproxy/src/net/websockets/websocket_channel.cc b/naiveproxy/src/net/websockets/websocket_channel.cc index f9eca41345..a12711e482 100644 --- a/naiveproxy/src/net/websockets/websocket_channel.cc +++ b/naiveproxy/src/net/websockets/websocket_channel.cc @@ -212,7 +212,7 @@ class WebSocketChannel::ConnectDelegate void OnFailure(const std::string& message, int net_error, - absl::optional response_code) override { + std::optional response_code) override { creator_->OnConnectFailure(message, net_error, response_code); // |this| has been deleted. } @@ -236,7 +236,7 @@ class WebSocketChannel::ConnectDelegate scoped_refptr headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials) override { + std::optional* credentials) override { return creator_->OnAuthRequired(auth_info, std::move(headers), remote_endpoint, std::move(callback), credentials); @@ -440,8 +440,7 @@ void WebSocketChannel::SendAddChannelRequestWithSuppliedCallback( if (!socket_url.SchemeIsWSOrWSS()) { // TODO(ricea): Kill the renderer (this error should have been caught by // Javascript). - event_interface_->OnFailChannel("Invalid scheme", ERR_FAILED, - absl::nullopt); + event_interface_->OnFailChannel("Invalid scheme", ERR_FAILED, std::nullopt); // |this| is deleted here. return; } @@ -479,7 +478,7 @@ void WebSocketChannel::OnConnectSuccess( void WebSocketChannel::OnConnectFailure(const std::string& message, int net_error, - absl::optional response_code) { + std::optional response_code) { DCHECK_EQ(CONNECTING, state_); // Copy the message before we delete its owner. @@ -507,7 +506,7 @@ int WebSocketChannel::OnAuthRequired( scoped_refptr response_headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials) { + std::optional* credentials) { return event_interface_->OnAuthRequired( auth_info, std::move(response_headers), remote_endpoint, std::move(callback), credentials); @@ -931,7 +930,7 @@ void WebSocketChannel::FailChannel(const std::string& message, // handshake. stream_->Close(); SetState(CLOSED); - event_interface_->OnFailChannel(message, ERR_FAILED, absl::nullopt); + event_interface_->OnFailChannel(message, ERR_FAILED, std::nullopt); } ChannelState WebSocketChannel::SendClose(uint16_t code, diff --git a/naiveproxy/src/net/websockets/websocket_channel.h b/naiveproxy/src/net/websockets/websocket_channel.h index 69c65b577e..f04e5d9bcf 100644 --- a/naiveproxy/src/net/websockets/websocket_channel.h +++ b/naiveproxy/src/net/websockets/websocket_channel.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -24,7 +25,6 @@ #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_frame.h" #include "net/websockets/websocket_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" namespace url { @@ -212,7 +212,7 @@ class NET_EXPORT WebSocketChannel { // failure to the event interface. May delete |this|. void OnConnectFailure(const std::string& message, int net_error, - absl::optional response_code); + std::optional response_code); // SSL certificate error callback from // WebSocketStream::CreateAndConnectStream(). Forwards the request to the @@ -230,7 +230,7 @@ class NET_EXPORT WebSocketChannel { scoped_refptr response_headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials); + std::optional* credentials); // Sets |state_| to |new_state| and updates UMA if necessary. void SetState(State new_state); diff --git a/naiveproxy/src/net/websockets/websocket_event_interface.h b/naiveproxy/src/net/websockets/websocket_event_interface.h index caf5e4e898..4391dd176f 100644 --- a/naiveproxy/src/net/websockets/websocket_event_interface.h +++ b/naiveproxy/src/net/websockets/websocket_event_interface.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -15,7 +16,6 @@ #include "base/functional/callback_forward.h" #include "base/memory/scoped_refptr.h" #include "net/base/net_export.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -100,13 +100,13 @@ class NET_EXPORT WebSocketEventInterface { // |message| is a human readable string describing the failure. (It may be // empty.) |net_error| contains the network error code for the failure, which // may be |OK| if the failure was at a higher level. |response_code| contains - // the HTTP status code that caused the failure, or |absl::nullopt| if the + // the HTTP status code that caused the failure, or |std::nullopt| if the // attempt didn't get that far. // // This function deletes the Channel. virtual void OnFailChannel(const std::string& message, int net_error, - absl::optional response_code) = 0; + std::optional response_code) = 0; // Called when the browser starts the WebSocket Opening Handshake. virtual void OnStartOpeningHandshake( @@ -153,7 +153,7 @@ class NET_EXPORT WebSocketEventInterface { scoped_refptr response_headers, const IPEndPoint& socket_address, base::OnceCallback callback, - absl::optional* credentials) = 0; + std::optional* credentials) = 0; protected: WebSocketEventInterface() = default; diff --git a/naiveproxy/src/net/websockets/websocket_extension.cc b/naiveproxy/src/net/websockets/websocket_extension.cc index 84ef0e606d..52f3674fdd 100644 --- a/naiveproxy/src/net/websockets/websocket_extension.cc +++ b/naiveproxy/src/net/websockets/websocket_extension.cc @@ -44,10 +44,10 @@ bool WebSocketExtension::Equals(const WebSocketExtension& other) const { std::multimap this_parameters, other_parameters; for (const auto& p : parameters_) { - this_parameters.insert(std::make_pair(p.name(), p.value())); + this_parameters.emplace(p.name(), p.value()); } for (const auto& p : other.parameters_) { - other_parameters.insert(std::make_pair(p.name(), p.value())); + other_parameters.emplace(p.name(), p.value()); } return this_parameters == other_parameters; } diff --git a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc index 165851170e..c87fc5d82a 100644 --- a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.cc @@ -96,7 +96,7 @@ int WebSocketHttp2HandshakeStream::SendRequest( if (!session_) { const int rv = ERR_CONNECTION_CLOSED; - OnFailure("Connection closed before sending request.", rv, absl::nullopt); + OnFailure("Connection closed before sending request.", rv, std::nullopt); return rv; } @@ -105,7 +105,7 @@ int WebSocketHttp2HandshakeStream::SendRequest( IPEndPoint address; int result = session_->GetPeerAddress(&address); if (result != OK) { - OnFailure("Error getting IP address.", result, absl::nullopt); + OnFailure("Error getting IP address.", result, std::nullopt); return result; } http_response_info_->remote_endpoint = address; @@ -324,7 +324,7 @@ void WebSocketHttp2HandshakeStream::OnClose(int status) { result_ = HandshakeResult::HTTP2_FAILED; OnFailure(base::StrCat({"Stream closed with error: ", ErrorToString(status)}), - status, absl::nullopt); + status, std::nullopt); if (callback_) std::move(callback_).Run(status); @@ -393,14 +393,14 @@ int WebSocketHttp2HandshakeStream::ValidateUpgradeResponse( const int rv = ERR_INVALID_RESPONSE; OnFailure("Error during WebSocket handshake: " + failure_message, rv, - absl::nullopt); + std::nullopt); return rv; } void WebSocketHttp2HandshakeStream::OnFailure( const std::string& message, int net_error, - absl::optional response_code) { + std::optional response_code) { stream_request_->OnFailure(message, net_error, response_code); } diff --git a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h index 0d6ed0dfbf..fe5f3f5a15 100644 --- a/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_http2_handshake_stream.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,6 @@ #include "net/websockets/websocket_basic_stream_adapters.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -130,7 +130,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp2HandshakeStream void OnFailure(const std::string& message, int net_error, - absl::optional response_code); + std::optional response_code); HandshakeResult result_ = HandshakeResult::HTTP2_INCOMPLETE; diff --git a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc index d1a0d35626..4388025600 100644 --- a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.cc @@ -93,7 +93,7 @@ int WebSocketHttp3HandshakeStream::SendRequest( if (!session_) { constexpr int rv = ERR_CONNECTION_CLOSED; - OnFailure("Connection closed before sending request.", rv, absl::nullopt); + OnFailure("Connection closed before sending request.", rv, std::nullopt); return rv; } @@ -102,7 +102,7 @@ int WebSocketHttp3HandshakeStream::SendRequest( IPEndPoint address; int result = session_->GetPeerAddress(&address); if (result != OK) { - OnFailure("Error getting IP address.", result, absl::nullopt); + OnFailure("Error getting IP address.", result, std::nullopt); return result; } http_response_info_->remote_endpoint = address; @@ -321,7 +321,7 @@ void WebSocketHttp3HandshakeStream::OnClose(int status) { } OnFailure(base::StrCat({"Stream closed with error: ", ErrorToString(status)}), - status, absl::nullopt); + status, std::nullopt); if (callback_) { std::move(callback_).Run(status); @@ -380,7 +380,7 @@ int WebSocketHttp3HandshakeStream::ValidateUpgradeResponse( const int rv = ERR_INVALID_RESPONSE; OnFailure("Error during WebSocket handshake: " + failure_message, rv, - absl::nullopt); + std::nullopt); return rv; } @@ -388,7 +388,7 @@ int WebSocketHttp3HandshakeStream::ValidateUpgradeResponse( void WebSocketHttp3HandshakeStream::OnFailure( const std::string& message, int net_error, - absl::optional response_code) { + std::optional response_code) { stream_request_->OnFailure(message, net_error, response_code); } diff --git a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h index 2176cb3193..def1976262 100644 --- a/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h +++ b/naiveproxy/src/net/websockets/websocket_http3_handshake_stream.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include "net/websockets/websocket_basic_stream_adapters.h" #include "net/websockets/websocket_handshake_stream_base.h" #include "net/websockets/websocket_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace net { @@ -127,7 +127,7 @@ class NET_EXPORT_PRIVATE WebSocketHttp3HandshakeStream final void OnFailure(const std::string& message, int net_error, - absl::optional response_code); + std::optional response_code); HandshakeResult result_ = HandshakeResult::HTTP3_INCOMPLETE; diff --git a/naiveproxy/src/net/websockets/websocket_inflater.cc b/naiveproxy/src/net/websockets/websocket_inflater.cc index 09198ed313..bc33277e1b 100644 --- a/naiveproxy/src/net/websockets/websocket_inflater.cc +++ b/naiveproxy/src/net/websockets/websocket_inflater.cc @@ -180,8 +180,8 @@ size_t WebSocketInflater::OutputBuffer::Size() const { std::pair WebSocketInflater::OutputBuffer::GetTail() { DCHECK_LT(tail_, buffer_.size()); - return std::make_pair(&buffer_[tail_], - std::min(capacity_ - Size(), buffer_.size() - tail_)); + return std::pair(&buffer_[tail_], + std::min(capacity_ - Size(), buffer_.size() - tail_)); } void WebSocketInflater::OutputBuffer::Read(char* dest, size_t size) { @@ -227,11 +227,11 @@ WebSocketInflater::InputQueue::~InputQueue() = default; std::pair WebSocketInflater::InputQueue::Top() { DCHECK(!IsEmpty()); if (buffers_.size() == 1) { - return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_], - tail_of_last_buffer_ - head_of_first_buffer_); + return std::pair(&buffers_.front()->data()[head_of_first_buffer_], + tail_of_last_buffer_ - head_of_first_buffer_); } - return std::make_pair(&buffers_.front()->data()[head_of_first_buffer_], - capacity_ - head_of_first_buffer_); + return std::pair(&buffers_.front()->data()[head_of_first_buffer_], + capacity_ - head_of_first_buffer_); } void WebSocketInflater::InputQueue::Push(const char* data, size_t size) { diff --git a/naiveproxy/src/net/websockets/websocket_stream.cc b/naiveproxy/src/net/websockets/websocket_stream.cc index d19bccce33..d99a33e9f9 100644 --- a/naiveproxy/src/net/websockets/websocket_stream.cc +++ b/naiveproxy/src/net/websockets/websocket_stream.cc @@ -4,6 +4,7 @@ #include "net/websockets/websocket_stream.h" +#include #include #include @@ -42,7 +43,6 @@ #include "net/websockets/websocket_handshake_stream_create_helper.h" #include "net/websockets/websocket_http2_handshake_stream.h" #include "net/websockets/websocket_http3_handshake_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" #include "url/origin.h" @@ -175,7 +175,7 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { void OnFailure(const std::string& message, int net_error, - absl::optional response_code) override { + std::optional response_code) override { if (api_delegate_) api_delegate_->OnFailure(message, net_error, response_code); failure_message_ = message; @@ -203,13 +203,13 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { ReportFailureWithMessage( "No handshake stream has been created or handshake stream is already " "destroyed.", - ERR_FAILED, absl::nullopt); + ERR_FAILED, std::nullopt); return; } if (!handshake_stream_->CanReadFromStream()) { ReportFailureWithMessage("Handshake stream is not readable.", - ERR_CONNECTION_CLOSED, absl::nullopt); + ERR_CONNECTION_CLOSED, std::nullopt); return; } @@ -241,7 +241,7 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { } } - void ReportFailure(int net_error, absl::optional response_code) { + void ReportFailure(int net_error, std::optional response_code) { DCHECK(timer_); timer_->Stop(); if (failure_message_.empty()) { @@ -268,7 +268,7 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { void ReportFailureWithMessage(const std::string& failure_message, int net_error, - absl::optional response_code) { + std::optional response_code) { connect_delegate_->OnFailure(failure_message, net_error, response_code); } @@ -308,8 +308,8 @@ class WebSocketStreamRequestImpl : public WebSocketStreamRequestAPI { // The failure information supplied by WebSocketBasicHandshakeStream, if any. std::string failure_message_; - absl::optional failure_net_error_; - absl::optional failure_response_code_; + std::optional failure_net_error_; + std::optional failure_response_code_; // A timer for handshake timeout. std::unique_ptr timer_; @@ -389,7 +389,7 @@ void Delegate::OnResponseStarted(URLRequest* request, int net_error) { if (net_error != OK) { DVLOG(3) << "OnResponseStarted (request failed)"; - owner_->ReportFailure(net_error, absl::nullopt); + owner_->ReportFailure(net_error, std::nullopt); return; } const int response_code = request->GetResponseCode(); @@ -401,7 +401,7 @@ void Delegate::OnResponseStarted(URLRequest* request, int net_error) { return; } - owner_->ReportFailure(net_error, absl::nullopt); + owner_->ReportFailure(net_error, std::nullopt); return; } @@ -428,7 +428,7 @@ void Delegate::OnResponseStarted(URLRequest* request, int net_error) { void Delegate::OnAuthRequired(URLRequest* request, const AuthChallengeInfo& auth_info) { - absl::optional credentials; + std::optional credentials; // This base::Unretained(this) relies on an assumption that |callback| can // be called called during the opening handshake. int rv = owner_->connect_delegate()->OnAuthRequired( @@ -442,7 +442,7 @@ void Delegate::OnAuthRequired(URLRequest* request, return; if (rv != OK) { request->LogUnblocked(); - owner_->ReportFailure(rv, absl::nullopt); + owner_->ReportFailure(rv, std::nullopt); return; } OnAuthRequiredComplete(request, nullptr); diff --git a/naiveproxy/src/net/websockets/websocket_stream.h b/naiveproxy/src/net/websockets/websocket_stream.h index 07c9c7af4f..c8dc6e1aa5 100644 --- a/naiveproxy/src/net/websockets/websocket_stream.h +++ b/naiveproxy/src/net/websockets/websocket_stream.h @@ -6,6 +6,7 @@ #define NET_WEBSOCKETS_WEBSOCKET_STREAM_H_ #include +#include #include #include @@ -20,7 +21,6 @@ #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_handshake_request_info.h" #include "net/websockets/websocket_handshake_response_info.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -77,7 +77,7 @@ class NET_EXPORT_PRIVATE WebSocketStreamRequestAPI WebSocketHttp3HandshakeStream* handshake_stream) = 0; virtual void OnFailure(const std::string& message, int net_error, - absl::optional response_code) = 0; + std::optional response_code) = 0; }; // WebSocketStream is a transport-agnostic interface for reading and writing @@ -113,7 +113,7 @@ class NET_EXPORT_PRIVATE WebSocketStream { // |message| contains defails of the failure. virtual void OnFailure(const std::string& message, int net_error, - absl::optional response_code) = 0; + std::optional response_code) = 0; // Called when the WebSocket Opening Handshake starts. virtual void OnStartOpeningHandshake( @@ -143,7 +143,7 @@ class NET_EXPORT_PRIVATE WebSocketStream { scoped_refptr response_headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials) = 0; + std::optional* credentials) = 0; }; // Create and connect a WebSocketStream of an appropriate type. The actual diff --git a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc index 4b4d525fa9..19d49e0bcf 100644 --- a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc +++ b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.cc @@ -57,7 +57,7 @@ class WebSocketStreamCreateTestBase::TestConnectDelegate void OnFailure(const std::string& message, int net_error, - absl::optional response_code) override { + std::optional response_code) override { owner_->has_failed_ = true; owner_->failure_message_ = message; owner_->failure_response_code_ = response_code.value_or(-1); @@ -86,7 +86,7 @@ class WebSocketStreamCreateTestBase::TestConnectDelegate scoped_refptr response_headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials) override { + std::optional* credentials) override { owner_->run_loop_waiting_for_on_auth_required_.Quit(); owner_->auth_challenge_info_ = auth_info; *credentials = owner_->auth_credentials_; diff --git a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h index 04979b34c3..b0cce087ea 100644 --- a/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h +++ b/naiveproxy/src/net/websockets/websocket_stream_create_test_base.h @@ -6,6 +6,7 @@ #define NET_WEBSOCKETS_WEBSOCKET_STREAM_CREATE_TEST_BASE_H_ #include +#include #include #include #include @@ -21,7 +22,6 @@ #include "net/test/test_with_task_environment.h" #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_test_util.h" -#include "third_party/abseil-cpp/absl/types/optional.h" class GURL; @@ -108,7 +108,7 @@ class WebSocketStreamCreateTestBase : public WithTaskEnvironment { base::OnceCallback on_auth_required_callback_; // This value will be copied to |*credentials| on OnAuthRequired. - absl::optional auth_credentials_; + std::optional auth_credentials_; // OnAuthRequired returns this value. int on_auth_required_rv_ = OK; diff --git a/naiveproxy/src/net/websockets/websocket_test_util.cc b/naiveproxy/src/net/websockets/websocket_test_util.cc index 6b8cdecbbe..b6d1a56176 100644 --- a/naiveproxy/src/net/websockets/websocket_test_util.cc +++ b/naiveproxy/src/net/websockets/websocket_test_util.cc @@ -279,7 +279,7 @@ int DummyConnectDelegate::OnAuthRequired( scoped_refptr response_headers, const IPEndPoint& host_port_pair, base::OnceCallback callback, - absl::optional* credentials) { + std::optional* credentials) { return OK; } diff --git a/naiveproxy/src/net/websockets/websocket_test_util.h b/naiveproxy/src/net/websockets/websocket_test_util.h index ec0ba5ec5e..f1b7e7e069 100644 --- a/naiveproxy/src/net/websockets/websocket_test_util.h +++ b/naiveproxy/src/net/websockets/websocket_test_util.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -25,7 +26,6 @@ #include "net/websockets/websocket_event_interface.h" #include "net/websockets/websocket_handshake_stream_create_helper.h" #include "net/websockets/websocket_stream.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace url { class Origin; @@ -210,7 +210,7 @@ class DummyConnectDelegate : public WebSocketStream::ConnectDelegate { std::unique_ptr response) override {} void OnFailure(const std::string& message, int net_error, - absl::optional response_code) override {} + std::optional response_code) override {} void OnStartOpeningHandshake( std::unique_ptr request) override {} void OnSSLCertificateError( @@ -223,7 +223,7 @@ class DummyConnectDelegate : public WebSocketStream::ConnectDelegate { scoped_refptr response_headers, const IPEndPoint& remote_endpoint, base::OnceCallback callback, - absl::optional* credentials) override; + std::optional* credentials) override; }; // WebSocketStreamRequestAPI implementation that sets the value of @@ -240,7 +240,7 @@ class TestWebSocketStreamRequestAPI : public WebSocketStreamRequestAPI { WebSocketHttp3HandshakeStream* handshake_stream) override; void OnFailure(const std::string& message, int net_error, - absl::optional response_code) override {} + std::optional response_code) override {} }; // A sub-class of WebSocketHandshakeStreamCreateHelper which sets a diff --git a/naiveproxy/src/third_party/abseil-cpp/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/BUILD.bazel index 79fb0ecd73..03122a958e 100644 --- a/naiveproxy/src/third_party/abseil-cpp/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/BUILD.bazel @@ -1,4 +1,3 @@ -# # Copyright 2020 The Abseil Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,3 +22,14 @@ exports_files([ "AUTHORS", "LICENSE", ]) + +# For building with clang-cl. +# https://bazel.build/configure/windows#clang +platform( + name = "x64_windows-clang-cl", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + "@bazel_tools//tools/cpp:clang-cl", + ], +) diff --git a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn index 846812e836..9d316b9404 100644 --- a/naiveproxy/src/third_party/abseil-cpp/BUILD.gn +++ b/naiveproxy/src/third_party/abseil-cpp/BUILD.gn @@ -205,6 +205,7 @@ if (build_with_chromium) { "absl/container:fixed_array_test", "absl/container:flat_hash_map_test", "absl/container:flat_hash_set_test", + "absl/container:hash_function_defaults_test", "absl/container:inlined_vector_test", "absl/container:node_slot_policy_test", "absl/container:raw_hash_set_allocator_test", diff --git a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilHelpers.cmake b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilHelpers.cmake index bd1c71b073..44f5bb3f0c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilHelpers.cmake +++ b/naiveproxy/src/third_party/abseil-cpp/CMake/AbseilHelpers.cmake @@ -186,8 +186,16 @@ function(absl_cc_library) endif() endif() endforeach() + set(skip_next_cflag OFF) foreach(cflag ${ABSL_CC_LIB_COPTS}) - if(${cflag} MATCHES "^(-Wno|/wd)") + if(skip_next_cflag) + set(skip_next_cflag OFF) + elseif(${cflag} MATCHES "^-Xarch_") + # An -Xarch_ flag implies that its successor only applies to the + # specified platform. Filter both of them out before the successor + # reaches the "^-m" filter. + set(skip_next_cflag ON) + elseif(${cflag} MATCHES "^(-Wno|/wd)") # These flags are needed to suppress warnings that might fire in our headers. set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") elseif(${cflag} MATCHES "^(-W|/w[1234eo])") diff --git a/naiveproxy/src/third_party/abseil-cpp/DIR_METADATA b/naiveproxy/src/third_party/abseil-cpp/DIR_METADATA index 2aaf8e2eed..744e51f4bb 100644 --- a/naiveproxy/src/third_party/abseil-cpp/DIR_METADATA +++ b/naiveproxy/src/third_party/abseil-cpp/DIR_METADATA @@ -1,3 +1,6 @@ -monorail { +monorail: { component: "Internals>Core" } +buganizer_public: { + component_id: 1456128 +} diff --git a/naiveproxy/src/third_party/abseil-cpp/MODULE.bazel b/naiveproxy/src/third_party/abseil-cpp/MODULE.bazel index 18190e8e79..fc1534a76c 100644 --- a/naiveproxy/src/third_party/abseil-cpp/MODULE.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/MODULE.bazel @@ -20,6 +20,9 @@ module( compatibility_level = 1, ) +cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension") +use_repo(cc_configure, "local_config_cc") + # Only direct dependencies need to be listed below. # Please keep the versions in sync with the versions in the WORKSPACE file. diff --git a/naiveproxy/src/third_party/abseil-cpp/PrivacyInfo.xcprivacy b/naiveproxy/src/third_party/abseil-cpp/PrivacyInfo.xcprivacy new file mode 100644 index 0000000000..3ff4a9d98b --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyCollectedDataTypes + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + diff --git a/naiveproxy/src/third_party/abseil-cpp/README.chromium b/naiveproxy/src/third_party/abseil-cpp/README.chromium index 089a795f12..614fba0659 100644 --- a/naiveproxy/src/third_party/abseil-cpp/README.chromium +++ b/naiveproxy/src/third_party/abseil-cpp/README.chromium @@ -4,7 +4,7 @@ URL: https://github.com/abseil/abseil-cpp License: Apache 2.0 License File: LICENSE Version: 0 -Revision: 10f3e6117b1154ca8e7e744809d82988f0ff481d +Revision: 797501d12ea767dabdc8d36674e083869e62ee7d Security Critical: yes Shipped: yes diff --git a/naiveproxy/src/third_party/abseil-cpp/WORKSPACE.bzlmod b/naiveproxy/src/third_party/abseil-cpp/WORKSPACE.bzlmod new file mode 100644 index 0000000000..83e67baa73 --- /dev/null +++ b/naiveproxy/src/third_party/abseil-cpp/WORKSPACE.bzlmod @@ -0,0 +1,19 @@ +# Copyright 2024 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# https://bazel.build/external/migration#workspace.bzlmod +# +# This file is intentionally empty. When bzlmod is enabled and this +# file exists, the contents of WORKSPACE is ignored. This prevents +# bzlmod builds from unintentionally depending on the WORKSPACE file. diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/BUILD.bazel index 14c30b38cd..253c0aeff4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/BUILD.bazel @@ -68,17 +68,6 @@ config_setting( visibility = [":__subpackages__"], ) -# x64_windows-clang-cl - used for selecting clang-cl for CI builds -platform( - name = "x64_windows-clang-cl", - constraint_values = [ - "@platforms//cpu:x86_64", - "@platforms//os:windows", - "@bazel_tools//tools/cpp:clang-cl", - ], - visibility = [":__subpackages__"], -) - config_setting( name = "osx", constraint_values = [ diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/abseil.podspec.gen.py b/naiveproxy/src/third_party/abseil-cpp/absl/abseil.podspec.gen.py index 63752980d0..c83edbfe5c 100755 --- a/naiveproxy/src/third_party/abseil-cpp/absl/abseil.podspec.gen.py +++ b/naiveproxy/src/third_party/abseil-cpp/absl/abseil.podspec.gen.py @@ -30,6 +30,9 @@ Pod::Spec.new do |s| :git => 'https://github.com/abseil/abseil-cpp.git', :tag => '${tag}', } + s.resource_bundles = { + s.module_name => 'PrivacyInfo.xcprivacy', + } s.module_name = 'absl' s.header_mappings_dir = 'absl' s.header_dir = 'absl' diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel index 737fd661ef..127d02338f 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/BUILD.bazel @@ -291,7 +291,7 @@ cc_library( cc_library( name = "atomic_hook_test_helper", - testonly = 1, + testonly = True, srcs = ["internal/atomic_hook_test_helper.cc"], hdrs = ["internal/atomic_hook_test_helper.h"], copts = ABSL_DEFAULT_COPTS, @@ -377,7 +377,7 @@ cc_test( cc_library( name = "exception_testing", - testonly = 1, + testonly = True, hdrs = ["internal/exception_testing.h"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -401,7 +401,7 @@ cc_library( cc_library( name = "exception_safety_testing", - testonly = 1, + testonly = True, srcs = ["internal/exception_safety_testing.cc"], hdrs = ["internal/exception_safety_testing.h"], copts = ABSL_TEST_COPTS, @@ -467,7 +467,7 @@ cc_test( # AbslInternalSpinLockDelay and AbslInternalSpinLockWake. cc_library( name = "spinlock_test_common", - testonly = 1, + testonly = True, srcs = ["spinlock_test_common.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -504,7 +504,7 @@ cc_test( cc_library( name = "spinlock_benchmark_common", - testonly = 1, + testonly = True, srcs = ["internal/spinlock_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -524,7 +524,7 @@ cc_library( cc_binary( name = "spinlock_benchmark", - testonly = 1, + testonly = True, copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["benchmark"], @@ -605,7 +605,7 @@ cc_test( cc_binary( name = "no_destructor_benchmark", - testonly = 1, + testonly = True, srcs = ["no_destructor_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -707,7 +707,7 @@ cc_test( cc_library( name = "scoped_set_env", - testonly = 1, + testonly = True, srcs = ["internal/scoped_set_env.cc"], hdrs = ["internal/scoped_set_env.h"], linkopts = ABSL_DEFAULT_LINKOPTS, @@ -781,7 +781,7 @@ cc_test( cc_binary( name = "strerror_benchmark", - testonly = 1, + testonly = True, srcs = ["internal/strerror_benchmark.cc"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, diff --git a/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h b/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h index f21dcb3ca8..38086a82e4 100644 --- a/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h +++ b/naiveproxy/src/third_party/abseil-cpp/absl/base/attributes.h @@ -843,15 +843,11 @@ // See also the upstream documentation: // https://clang.llvm.org/docs/AttributeReference.html#trivial-abi // -#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi) -#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]] -#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1 -#elif ABSL_HAVE_ATTRIBUTE(trivial_abi) -#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi)) -#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1 -#else +// b/321691395 - This is currently disabled in open-source builds since +// compiler support differs. If system libraries compiled with GCC are mixed +// with libraries compiled with Clang, types will have different ideas about +// their ABI, leading to hard to debug crashes. #define ABSL_ATTRIBUTE_TRIVIAL_ABI -#endif // ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS // @@ -875,4 +871,51 @@ #define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS #endif +// ABSL_ATTRIBUTE_UNINITIALIZED +// +// GCC and Clang support a flag `-ftrivial-auto-var-init=