Update googleurl to the latest version from Chromium Version used is cabce318aaa096f18dee72eb09b0bddf1565cd2b from Tue Feb 22 09:08:34 2022 +0000. Change-Id: Ia8646e29a6780b3d8f3dab275c2513e012b3546f
diff --git a/AUTHORS b/AUTHORS index 012e246..364df55 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -47,6 +47,7 @@ Alec Petridis <alecthechop@gmail.com> Aleksandar Stojiljkovic <aleksandar.stojiljkovic@intel.com> Aleksei Gurianov <gurianov@gmail.com> +Alesandro Ortiz <alesandro@alesandroortiz.com> Alex Chronopoulos <achronop@gmail.com> Alex Gabriel <minilogo@gmail.com> Alex Gartrell <agartrell@cmu.edu> @@ -88,10 +89,12 @@ anatoly techtonik <techtonik@gmail.com> Ancil George <ancilgeorge@samsung.com> Andra Paraschiv <andra.paraschiv@intel.com> +Andras Tokodi <a.tokodi@eyeo.com> Andreas Papacharalampous <andreas@apap04.com> Andrei Borza <andrei.borza@gmail.com> Andrei Parvu <andrei.prv@gmail.com> Andrei Parvu <parvu@adobe.com> +Andres Salomon <dilinger@queued.net> Andreu Botella <andreu@andreubotella.com> Andrew Boyarshin <andrew.boyarshin@gmail.com> Andrew Brampton <me@bramp.net> @@ -183,6 +186,7 @@ Caio Marcelo de Oliveira Filho <caio.de.oliveira.filho@intel.com> Caitlin Potter <caitpotter88@gmail.com> Calvin Mei <calvimei@amazon.com> +Calvin Watford <watfordcalvin@gmail.com> Cameron Gutman <aicommander@gmail.com> Camille Viot <viot.camille@outlook.com> Carlos Santa <carlos.santa@intel.com> @@ -251,8 +255,10 @@ Daniel Waxweiler <daniel.waxweiler@gmail.com> Dániel Bátyai <dbatyai@inf.u-szeged.hu> Dániel Vince <vinced@inf.u-szeged.hu> +Daniil Suvorov <severecloud@gmail.com> Daoming Qiu <daoming.qiu@intel.com> Darik Harter <darik.harter@gmail.com> +Darshan Sen <raisinten@gmail.com> Darshini KN <kn.darshini@samsung.com> Dave Vandyke <kzar@kzar.co.uk> David Benjamin <davidben@mit.edu> @@ -342,6 +348,7 @@ Fabien Tassin <fta@sofaraway.org> Felipe Erias Morandeira <felipeerias@gmail.com> Felix H. Dahlke <fhd@ubercode.de> +Felix Weilbach <feweilbach@gmail.com> Fengrong Fang <fr.fang@samsung.com> Fernando Jiménez Moreno <ferjmoreno@gmail.com> Finbar Crago <finbar.crago@gmail.com> @@ -408,6 +415,7 @@ Heeyoun Lee <heeyoun.lee@samsung.com> Henrique Limas <henrique.ramos.limas@gmail.com> Himanshu Joshi <h.joshi@samsung.com> +Hiroyuki Matsuda <gsittyz@gmail.com> Hodol Han <bab6ting@gmail.com> Holger Kraus <kraush@amazon.com> Hong Zheng <hong.zheng@intel.com> @@ -476,6 +484,7 @@ James Wei <james.wei@intel.com> James Willcox <jwillcox@litl.com> Jan Grulich <grulja@gmail.com> +Jan Keitel <jan.keitel@gmail.com> Jan Rucka <ruckajan10@gmail.com> Jan Sauer <jan@jansauer.de> Janusz Majnert <jmajnert@gmail.com> @@ -535,6 +544,7 @@ Jinyoung Hur <hur.ims@navercorp.com> Jinyoung Hur <hurims@gmail.com> Jitendra Kumar Sahoo <jitendra.ks@samsung.com> +Jitesh Pareek <j1.pareek@samsung.com> Joachim Bauch <jbauch@webrtc.org> Joachim Bauch <mail@joachim-bauch.de> Joanmarie Diggs <joanmarie.diggs@gmail.com> @@ -553,6 +563,7 @@ Jonathan Garbee <jonathan@garbee.me> Jonathan Hacker <jhacker@arcanefour.com> Jonathan Kingston <kingstonmailbox@gmail.com> +Jonathan Shimonovich <jonathans@talon-sec.com> Jongdeok Kim <jongdeok.kim@navercorp.com> Jongheon Kim <sapzape@gmail.com> JongKwon Lee <jongkwon.lee@navercorp.com> @@ -592,6 +603,7 @@ Justin Okamoto <justmoto@amazon.com> Justin Ribeiro <justin@justinribeiro.com> Jüri Valdmann <juri.valdmann@qt.io> +Juyoung Kim <chattank05@gmail.com> Kai Jiang <jiangkai@gmail.com> Kai Köhne <kai.koehne@qt.io> Kai Uwe Broulik <kde@privat.broulik.de> @@ -610,6 +622,7 @@ Kaustubh Atrawalkar <kaustubh.a@samsung.com> Kaustubh Atrawalkar <kaustubh.ra@gmail.com> Ke He <ke.he@intel.com> +Keeley Hammond <vertedinde@electronjs.org> Keene Pan <keenepan@linpus.com> Keiichiro Nagashima <n4ag3a2sh1i@gmail.com> Keita Suzuki <keitasuzuki.park@gmail.com> @@ -645,6 +658,7 @@ Kui Tan <tk1061178@gmail.com> Kunal Thakar <kunalt@gmail.com> Kushal Pisavadia <kushi.p@gmail.com> +Kwanghee Lee <ekwange@gmail.com> Kwangho Shin <k_h.shin@samsung.com> Kyle Nahrgang <kpn24@drexel.edu> Kyle Plumadore <kyle.plumadore@amd.com> @@ -682,6 +696,7 @@ Lorenzo Stoakes <lstoakes@gmail.com> Lu Guanqun <guanqun.lu@gmail.com> Luc Shi <lei.a.shi@intel.com> +Luca Casonato <luccasonato@gmail.com> Luca Di Domenico <luca94dd@gmail.com> Lucie Brozkova <lucinka.brozkova@gmail.com> Luiz Von Dentz <luiz.von.dentz@intel.com> @@ -790,6 +805,7 @@ Miran Karic <miran.karic@imgtec.com> Mirela Budaes <mbudaes@adobe.com> Mirela Budaes <mbudaes@gmail.com> +Mitchell Cohen <mitchell@agilebits.com> Miyoung Shin <myid.shin@navercorp.com> Mohamed I. Hammad <ibraaaa@gmail.com> Mohamed Mansour <m0.interactive@gmail.com> @@ -797,6 +813,7 @@ Mohammed Wajahat Ali Siddiqui <wajahat.s@samsung.com> Mohan Reddy <mohan.reddy@samsung.com> Mohit Bhalla <bhallam@amazon.com> +Momoka Yamamoto <momoka.my6@gmail.com> Momoko Hattori <momohatt10@gmail.com> Mostafa Sedaghat joo <mostafa.sedaghat@gmail.com> Mrunal Kapade <mrunal.kapade@intel.com> @@ -954,6 +971,7 @@ Rosen Dash <rosen.dash@gmail.com> Ross Kirsling <rkirsling@gmail.com> Ross Wollman <ross.wollman@gmail.com> +Roy Le <royle0502@gmail.com> Ruan Beihong <ruanbeihong@gmail.com> ruben <chromium@hybridsource.org> Ruben Bridgewater <ruben@bridgewater.de> @@ -1013,6 +1031,7 @@ Sergio Carlos Morales Angeles <carloschilazo@gmail.com> Sergio Garcia Murillo <sergio.garcia.murillo@gmail.com> Sergiy Belozorov <rryk.ua@gmail.com> +Serhii Matrunchyk <sergiy.matrunchyk@gmail.com> Seshadri Mahalingam <seshadri.mahalingam@gmail.com> Seungkyu Lee <zx6658@gmail.com> Sevan Janiyan <venture37@geeklan.co.uk> @@ -1100,6 +1119,7 @@ Sylvestre Ledru <sylvestre.ledru@gmail.com> Synthia Islam <synthia.is@samsung.com> Szabolcs David <davidsz@inf.u-szeged.hu> +Szilard Szaloki <szilardszaloki@gmail.com> Szymon Piechowicz <szymonpiechowicz@o2.pl> Taeheon Kim <skyrabbits1@gmail.com> Taeho Nam <thn7440@gmail.com> @@ -1108,7 +1128,9 @@ Taeyeon Kim <ssg9732@gmail.com> Tae Shin <taeshindev@gmail.com> Takaaki Suzuki <takaakisuzuki.14@gmail.com> +Takahiro Aoyagi <hogehoge@gachapin.jp> Takashi Fujita <tgfjt.mail@gmail.com> +Takashi Mima <tks.m1205@gmail.com> Takeshi Kurosawa <taken.spc@gmail.com> Tanay Chowdhury <tanay.c@samsung.com> Tanvir Rizvi <tanvir.rizvi@samsung.com> @@ -1133,6 +1155,7 @@ Timo Reimann <ttr314@googlemail.com> Timo Witte <timo.witte@gmail.com> Ting Shao <ting.shao@intel.com> +Tobias Lippert <tobias.lippert@fastmail.com> Tobias Soppa <tobias@soppa.me> Tobias Soppa <tobias.soppa@code.berlin> Tom Callaway <tcallawa@redhat.com> @@ -1150,6 +1173,7 @@ U. Artie Eoff <ullysses.a.eoff@intel.com> Umar Hansa <umar.hansa@gmail.com> Upendra Gowda <upendrag.gowda@gmail.com> +UwU UwU <uwu7586@gmail.com> Uzair Jaleel <uzair.jaleel@samsung.com> Vadim Gorbachev <bmsdave@gmail.com> Vaibhav Agrawal <vaibhav1.a@samsung.com> @@ -1174,6 +1198,7 @@ Vivek Galatage <vivek.vg@samsung.com> Volker Sorge <volker.sorge@gmail.com> Waihung Fu <fufranci@amazon.com> +wafuwafu13 <mariobaske@i.softbank.jp> Wojciech Bielawski <wojciech.bielawski@gmail.com> Wanming Lin <wanming.lin@intel.com> Wei Li <wei.c.li@intel.com> @@ -1186,6 +1211,7 @@ Will Cohen <wwcohen@gmail.com> Will Hirsch <chromium@willhirsch.co.uk> Will Shackleton <w.shackleton@gmail.com> +Will Watts <willwatts.ww@googlemail.com> William Xie <william.xie@intel.com> Winston Chen <winston.c1@samsung.com> Xiang Long <xiang.long@intel.com> @@ -1239,7 +1265,9 @@ Youngsun Suh <zard17@gmail.com> Yuan-Pin Yu <yjames@uber.com> Yuhong Sha <yuhong.sha@samsung.com> +Yuki Osaki <yuki.osaki7@gmail.com> Yuki Tsuchiya <Yuki.Tsuchiya@sony.com> +Yuma Takai <tara20070827@gmail.com> Yumikiyo Osanai <yumios.art@gmail.com> Yunchao He <yunchao.he@intel.com> Yupei Lin <yplam@yplam.com> @@ -1251,6 +1279,7 @@ Yuta Kasai <kasai.yuta0810@gmail.com> Yuvanesh Natarajan <yuvanesh.n1@samsung.com> Zach Bjornson <zbbjornson@gmail.com> +Zachary Capalbo <zach.geek@gmail.com> Zeno Albisser <zeno.albisser@digia.com> Zeqin Chen <talonchen@tencent.com> Zhang Hao <15686357310a@gmail.com> @@ -1267,6 +1296,7 @@ Zoltan Czirkos <czirkos.zoltan@gmail.com> Zoltan Herczeg <zherczeg.u-szeged@partner.samsung.com> Zoltan Kuscsik <zoltan.kuscsik@linaro.org> +Zoru Lee <donzoru@gmail.com> Zsolt Borbely <zsborbely.u-szeged@partner.samsung.com> 方觉 (Fang Jue) <fangjue23303@gmail.com> 迷渡 <justjavac@gmail.com> @@ -1276,6 +1306,7 @@ # BEGIN organizations section. Accenture <*@accenture.com> ACCESS CO., LTD. <*@access-company.com> +Ada Logics Ltd. <*@adalogics.com> Akamai Inc. <*@akamai.com> ARM Holdings <*@arm.com> BlackBerry Limited <*@blackberry.com> @@ -1318,11 +1349,13 @@ Mozilla Corporation <*@mozilla.com> Neverware Inc. <*@neverware.com> NIKE, Inc. <*@nike.com> +Nutanix Inc. <*nutanix.com> NVIDIA Corporation <*@nvidia.com> OpenFin Inc. <*@openfin.co> Opera Software ASA <*@opera.com> Optical Tone Ltd <*@opticaltone.com> Pengutronix e.K. <*@pengutronix.de> +Quality First Software GmbH <*@qf-software.com> Rakuten Kobo Inc. <*@kobo.com> Rakuten Kobo Inc. <*@rakuten.com> Red Hat Inc. <*@redhat.com> @@ -1332,15 +1365,18 @@ Spotify AB <*@spotify.com> Synaptics <*@synaptics.com> Tableau Software <*@tableau.com> +Talon Cyber Security Ltd. <*@talon-sec.com> TeamSpeak Systems GmbH <*@teamspeak.com> The Chromium Authors <*@chromium.org> The MathWorks, Inc. <binod.pant@mathworks.com> +THEO Technologies <*@theoplayer.com> Torchmobile Inc. Upwork <*@cloud.upwork.com> Venture 3 Systems LLC <*@venture3systems.com> Vewd Software AS <*@vewd.com> Vivaldi Technologies AS <*@vivaldi.com> Wacom <*@wacom.com> +Xperi Corporation <*@xperi.com> Yandex LLC <*@yandex-team.ru> # Please DO NOT APPEND here. See comments at the top of the file. # END organizations section.
diff --git a/base/BUILD b/base/BUILD index e2da292..d31df3e 100644 --- a/base/BUILD +++ b/base/BUILD
@@ -6,6 +6,14 @@ cc_library( name = "base", + srcs = [ + "debug/crash_logging.cc", + "strings/string_piece.cc", + "strings/string_util.cc", + "strings/string_util_constants.cc", + "strings/utf_string_conversion_utils.cc", + "strings/utf_string_conversions.cc", + ], hdrs = [ "compiler_specific.h", "containers/checked_iterators.h", @@ -15,22 +23,33 @@ "containers/util.h", "cxx17_backports.h", "cxx20_to_address.h", + "debug/crash_logging.h", "debug/leak_annotations.h", "functional/identity.h", "functional/invoke.h", "functional/not_fn.h", - "macros.h", + "memory/raw_ptr.h", "no_destructor.h", "ranges/algorithm.h", "ranges/functional.h", "ranges/ranges.h", "stl_util.h", "template_util.h", - ], + "strings/char_traits.h", + "strings/string_piece_forward.h", + "strings/string_piece.h", + "strings/string_util.h", + "strings/string_util_internal.h", + "strings/string_number_conversions.h", + "strings/utf_string_conversions.h", + "strings/utf_string_conversion_utils.h", + ] + build_config.strings_hdrs, copts = build_config.default_copts, visibility = ["//visibility:public"], deps = [ + "//base/third_party/icu", "//build:build_config", + "//build:buildflag", "//polyfills", "@com_google_absl//absl/types:optional", ],
diff --git a/base/compiler_specific.h b/base/compiler_specific.h index 58a7d0d..3a85453 100644 --- a/base/compiler_specific.h +++ b/base/compiler_specific.h
@@ -31,23 +31,6 @@ #define HAS_BUILTIN(x) 0 #endif -// Annotate a variable indicating it's ok if the variable is not used. -// (Typically used to silence a compiler warning when the assignment -// is important for some other reason.) -// Use like: -// int x = ...; -// ALLOW_UNUSED_LOCAL(x); -#define ALLOW_UNUSED_LOCAL(x) (void)x - -// Annotate a typedef or function indicating it's ok if it's not used. -// Use like: -// typedef Foo Bar ALLOW_UNUSED_TYPE; -#if defined(COMPILER_GCC) || defined(__clang__) -#define ALLOW_UNUSED_TYPE __attribute__((unused)) -#else -#define ALLOW_UNUSED_TYPE -#endif - // Annotate a function indicating it should not be inlined. // Use like: // NOINLINE void DoStuff() { ... } @@ -108,17 +91,6 @@ #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) #endif -// Annotate a function indicating the caller must examine the return value. -// Use like: -// int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in base/macros.h. -#undef WARN_UNUSED_RESULT -#if defined(COMPILER_GCC) || defined(__clang__) -#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define WARN_UNUSED_RESULT -#endif - // In case the compiler supports it NO_UNIQUE_ADDRESS evaluates to the C++20 // attribute [[no_unique_address]]. This allows annotating data members so that // they need not have an address distinct from all other non-static data members @@ -164,7 +136,7 @@ #endif // MemorySanitizer annotations. -#if defined(MEMORY_SANITIZER) && !defined(OS_NACL) +#if defined(MEMORY_SANITIZER) && !BUILDFLAG(IS_NACL) #include <sanitizer/msan_interface.h> // Mark a memory region fully initialized. @@ -194,7 +166,7 @@ // DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks. #if !defined(DISABLE_CFI_ICALL) -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) // Windows also needs __declspec(guard(nocf)). #define DISABLE_CFI_ICALL NO_SANITIZE("cfi-icall") __declspec(guard(nocf)) #else @@ -207,11 +179,11 @@ // Macro useful for writing cross-platform function pointers. #if !defined(CDECL) -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) #define CDECL __cdecl -#else // defined(OS_WIN) +#else // BUILDFLAG(IS_WIN) #define CDECL -#endif // defined(OS_WIN) +#endif // BUILDFLAG(IS_WIN) #endif // !defined(CDECL) // Macro for hinting that an expression is likely to be false. @@ -239,13 +211,6 @@ #define HAS_FEATURE(FEATURE) 0 #endif -// Macro for telling -Wimplicit-fallthrough that a fallthrough is intentional. -#if defined(__clang__) -#define FALLTHROUGH [[clang::fallthrough]] -#else -#define FALLTHROUGH -#endif - #if defined(COMPILER_GCC) #define PRETTY_FUNCTION __PRETTY_FUNCTION__ #elif defined(COMPILER_MSVC) @@ -354,13 +319,11 @@ #define ANALYZER_ASSUME_TRUE(arg) ::AnalyzerAssumeTrue(!!(arg)) #define ANALYZER_SKIP_THIS_PATH() static_cast<void>(::AnalyzerNoReturn()) -#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); #else // !defined(__clang_analyzer__) #define ANALYZER_ASSUME_TRUE(arg) (arg) #define ANALYZER_SKIP_THIS_PATH() -#define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var); #endif // defined(__clang_analyzer__) @@ -419,4 +382,12 @@ #define CONSTINIT #endif +#if defined(__clang__) +#define GSL_OWNER [[gsl::Owner]] +#define GSL_POINTER [[gsl::Pointer]] +#else +#define GSL_OWNER +#define GSL_POINTER +#endif + #endif // BASE_COMPILER_SPECIFIC_H_
diff --git a/base/containers/checked_iterators.h b/base/containers/checked_iterators.h index b5fe925..c4e1e69 100644 --- a/base/containers/checked_iterators.h +++ b/base/containers/checked_iterators.h
@@ -30,7 +30,7 @@ // Required for certain libc++ algorithm optimizations that are not available // for NaCl. -#if defined(_LIBCPP_VERSION) && !defined(OS_NACL) +#if defined(_LIBCPP_VERSION) && !BUILDFLAG(IS_NACL) template <typename Ptr> friend struct std::pointer_traits; #endif @@ -185,10 +185,10 @@ return current_[rhs]; } - static bool IsRangeMoveSafe(const CheckedContiguousIterator& from_begin, - const CheckedContiguousIterator& from_end, - const CheckedContiguousIterator& to) - WARN_UNUSED_RESULT { + [[nodiscard]] static bool IsRangeMoveSafe( + const CheckedContiguousIterator& from_begin, + const CheckedContiguousIterator& from_end, + const CheckedContiguousIterator& to) { if (from_end < from_begin) return false; const auto from_begin_uintptr = get_uintptr(from_begin.current_); @@ -217,7 +217,7 @@ } // namespace base -#if defined(_LIBCPP_VERSION) && !defined(OS_NACL) +#if defined(_LIBCPP_VERSION) && !BUILDFLAG(IS_NACL) // Specialize both std::__is_cpp17_contiguous_iterator and std::pointer_traits // for CCI in case we compile with libc++ outside of NaCl. The former is // required to enable certain algorithm optimizations (e.g. std::copy can be a
diff --git a/base/containers/span.h b/base/containers/span.h index 550eec8..1ba60b1 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -15,6 +15,7 @@ #include <utility> #include "polyfills/base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/checked_iterators.h" #include "base/containers/contiguous_iterator.h" #include "base/cxx17_backports.h" @@ -225,10 +226,6 @@ // sized container (e.g. std::vector) requires an explicit conversion (in the // C++20 draft this is simply UB) // -// Differences from [span.obs]: -// - empty() is marked with WARN_UNUSED_RESULT instead of [[nodiscard]] -// ([[nodiscard]] is a C++17 feature) -// // Furthermore, all constructors and methods are marked noexcept due to the lack // of exceptions in Chromium. // @@ -237,7 +234,7 @@ // [span], class template span template <typename T, size_t Extent> -class span : public internal::ExtentStorage<Extent> { +class GSL_POINTER span : public internal::ExtentStorage<Extent> { private: using ExtentStorage = internal::ExtentStorage<Extent>; @@ -408,9 +405,7 @@ // [span.obs], span observers constexpr size_t size() const noexcept { return ExtentStorage::size(); } constexpr size_t size_bytes() const noexcept { return size() * sizeof(T); } - constexpr bool empty() const noexcept WARN_UNUSED_RESULT { - return size() == 0; - } + [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access constexpr T& operator[](size_t idx) const noexcept {
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc new file mode 100644 index 0000000..f6bad4f --- /dev/null +++ b/base/debug/crash_logging.cc
@@ -0,0 +1,64 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/debug/crash_logging.h" + +namespace gurl_base { +namespace debug { + +namespace { + +CrashKeyImplementation* g_crash_key_impl = nullptr; + +} // namespace + +CrashKeyString* AllocateCrashKeyString(const char name[], + CrashKeySize value_length) { + if (!g_crash_key_impl) + return nullptr; + + return g_crash_key_impl->Allocate(name, value_length); +} + +void SetCrashKeyString(CrashKeyString* crash_key, gurl_base::StringPiece value) { + if (!g_crash_key_impl || !crash_key) + return; + + g_crash_key_impl->Set(crash_key, value); +} + +void ClearCrashKeyString(CrashKeyString* crash_key) { + if (!g_crash_key_impl || !crash_key) + return; + + g_crash_key_impl->Clear(crash_key); +} + +BASE_EXPORT void OutputCrashKeysToStream(std::ostream& out) { + if (!g_crash_key_impl) + return; + + g_crash_key_impl->OutputCrashKeysToStream(out); +} + +ScopedCrashKeyString::ScopedCrashKeyString(CrashKeyString* crash_key, + gurl_base::StringPiece value) + : crash_key_(crash_key) { + SetCrashKeyString(crash_key_, value); +} + +ScopedCrashKeyString::ScopedCrashKeyString(ScopedCrashKeyString&& other) + : crash_key_(std::exchange(other.crash_key_, nullptr)) {} + +ScopedCrashKeyString::~ScopedCrashKeyString() { + ClearCrashKeyString(crash_key_); +} + +void SetCrashKeyImplementation(std::unique_ptr<CrashKeyImplementation> impl) { + delete g_crash_key_impl; + g_crash_key_impl = impl.release(); +} + +} // namespace debug +} // namespace base
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h new file mode 100644 index 0000000..fdc5343 --- /dev/null +++ b/base/debug/crash_logging.h
@@ -0,0 +1,204 @@ +// Copyright (c) 2012 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 BASE_DEBUG_CRASH_LOGGING_H_ +#define BASE_DEBUG_CRASH_LOGGING_H_ + +#include <stddef.h> + +#include <iosfwd> +#include <memory> +#include <type_traits> + +#include "polyfills/base/base_export.h" +#include "base/cxx17_backports.h" +#include "base/memory/raw_ptr.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" + +namespace gurl_base { +namespace debug { + +// A crash key is an annotation that is carried along with a crash report, to +// provide additional debugging information beyond a stack trace. Crash keys +// have a name and a string value. +// +// The preferred API is //components/crash/core/common:crash_key, however not +// all clients can hold a direct dependency on that target. The API provided +// in this file indirects the dependency and adds some convenience helpers that +// make the API a bit less clunky. +// +// TODO(dcheng): Some of the nicer APIs should probably be upstreamed into +// //components/crash. +// +// Preferred usage when a crash key value only needs to be set within a scope: +// +// SCOPED_CRASH_KEY_STRING32("category", "name", "value"); +// gurl_base::debug::DumpWithoutCrashing(); +// +// If the crash key is pre-allocated elsewhere, but the value only needs to be +// set within a scope: +// +// gurl_base::debug::ScopedCrashKeyString scoper( +// GetCrashKeyForComponent(), +// "value"); +// +// Otherwise, if the crash key needs to persist (e.g. the actual crash dump is +// triggered some time later asynchronously): +// +// static auto* const crash_key = gurl_base::debug::AllocateCrashKeyString( +// "name", gurl_base::debug::CrashKeySize::Size32); +// gurl_base::debug::SetCrashKeyString(crash_key); +// +// // Do other work before calling `gurl_base::debug::DumpWithoutCrashing()` later. +// +// ***WARNING*** +// +// Do *not* write this: +// +// gurl_base::debug::SetCrashKeyString( +// gurl_base::debug::AllocateCrashKeyString( +// "name", gurl_base::debug::CrashKeySize::Size32), +// "value"); +// +// As this will leak a heap allocation every time the crash key is set! + +// The maximum length for a crash key's value must be one of the following +// pre-determined values. +enum class CrashKeySize { + Size32 = 32, + Size64 = 64, + Size256 = 256, +}; + +struct CrashKeyString; + +// Allocates a new crash key with the specified |name| with storage for a +// value up to length |size|. This will return null if the crash key system is +// not initialized. +// +// Note: this internally allocates, so the returned pointer should always +// be cached in a variable with static storage duration, e.g.: +// static auto* const crash_key = gurl_base::debug::AllocateCrashKeyString(...); +BASE_EXPORT CrashKeyString* AllocateCrashKeyString(const char name[], + CrashKeySize size); + +// Stores |value| into the specified |crash_key|. The |crash_key| may be null +// if AllocateCrashKeyString() returned null. If |value| is longer than the +// size with which the key was allocated, it will be truncated. +BASE_EXPORT void SetCrashKeyString(CrashKeyString* crash_key, + gurl_base::StringPiece value); + +// Clears any value that was stored in |crash_key|. The |crash_key| may be +// null. +BASE_EXPORT void ClearCrashKeyString(CrashKeyString* crash_key); + +// Outputs current (i.e. allocated and non-empty) crash keys to `out`. +BASE_EXPORT void OutputCrashKeysToStream(std::ostream& out); + +// A scoper that sets the specified key to value for the lifetime of the +// object, and clears it on destruction. +class BASE_EXPORT ScopedCrashKeyString { + public: + ScopedCrashKeyString(CrashKeyString* crash_key, gurl_base::StringPiece value); + ScopedCrashKeyString(ScopedCrashKeyString&& other); + ~ScopedCrashKeyString(); + + // Disallow copy and assign. + ScopedCrashKeyString(const ScopedCrashKeyString&) = delete; + ScopedCrashKeyString& operator=(const ScopedCrashKeyString&) = delete; + + // Disallow move assign to keep the time at which the crash key is cleared + // easy to reason about. Assigning over an existing instance would + // automatically clear the key instead of at the destruction of the object. + ScopedCrashKeyString& operator=(ScopedCrashKeyString&&) = delete; + + private: + raw_ptr<CrashKeyString> crash_key_; +}; + +// Internal helpers for the SCOPED_CRASH_KEY_... helper macros defined below. +// +// The static_assert that checks the length of |key_name| is a compile-time +// equivalent of the GURL_DCHECK in crash_reporter::internal::CrashKeyStringImpl::Set +// that restricts the name of a crash key to 40 characters. +#define SCOPED_CRASH_KEY_STRING_INTERNAL2(category, name, nonce, data, \ + key_size) \ + static_assert(::gurl_base::size(category "-" name) < 40, \ + "Crash key names must be shorter than 40 characters."); \ + ::gurl_base::debug::ScopedCrashKeyString scoped_crash_key_helper##nonce( \ + [] { \ + static auto* const key = ::gurl_base::debug::AllocateCrashKeyString( \ + category "-" name, key_size); \ + return key; \ + }(), \ + (data)) + +// This indirection is needed to expand __COUNTER__. +#define SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, nonce, data, \ + key_size) \ + SCOPED_CRASH_KEY_STRING_INTERNAL2(category, name, nonce, data, key_size) + +// Helper macros for putting a local variable crash key on the stack before +// causing a crash or calling CrashWithoutDumping(). `category` and `name` +// should be string literals. +// +// SCOPED_CRASH_KEY_STRING32("MyCategory", "key_name", "value"); +// +// will set the crash key annotation named "MyCategory-key_name" to "value" +// while in scope. +#define SCOPED_CRASH_KEY_STRING32(category, name, data) \ + SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \ + ::gurl_base::debug::CrashKeySize::Size32) + +#define SCOPED_CRASH_KEY_STRING64(category, name, data) \ + SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \ + ::gurl_base::debug::CrashKeySize::Size64) + +#define SCOPED_CRASH_KEY_STRING256(category, name, data) \ + SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \ + ::gurl_base::debug::CrashKeySize::Size256) + +#define SCOPED_CRASH_KEY_BOOL(category, name, data) \ + static_assert(std::is_same<std::decay_t<decltype(data)>, bool>::value, \ + "SCOPED_CRASH_KEY_BOOL must be passed a boolean value."); \ + SCOPED_CRASH_KEY_STRING32(category, name, (data) ? "true" : "false") + +#define SCOPED_CRASH_KEY_NUMBER(category, name, data) \ + SCOPED_CRASH_KEY_STRING32(category, name, ::gurl_base::NumberToString(data)) + +//////////////////////////////////////////////////////////////////////////////// +// The following declarations are used to initialize the crash key system +// in //base by providing implementations for the above functions. + +// The virtual interface that provides the implementation for the crash key +// API. This is implemented by a higher-layer component, and the instance is +// set using the function below. +class CrashKeyImplementation { + public: + virtual ~CrashKeyImplementation() = default; + + virtual CrashKeyString* Allocate(const char name[], CrashKeySize size) = 0; + virtual void Set(CrashKeyString* crash_key, gurl_base::StringPiece value) = 0; + virtual void Clear(CrashKeyString* crash_key) = 0; + virtual void OutputCrashKeysToStream(std::ostream& out) = 0; +}; + +// Initializes the crash key system in base by replacing the existing +// implementation, if it exists, with |impl|. The |impl| is copied into base. +BASE_EXPORT void SetCrashKeyImplementation( + std::unique_ptr<CrashKeyImplementation> impl); + +// The base structure for a crash key, storing the allocation metadata. +struct CrashKeyString { + constexpr CrashKeyString(const char name[], CrashKeySize size) + : name(name), size(size) {} + const char* const name; + const CrashKeySize size; +}; + +} // namespace debug +} // namespace base + +#endif // BASE_DEBUG_CRASH_LOGGING_H_
diff --git a/base/debug/leak_annotations.h b/base/debug/leak_annotations.h index b551552..89f47f4 100644 --- a/base/debug/leak_annotations.h +++ b/base/debug/leak_annotations.h
@@ -18,7 +18,7 @@ // ANNOTATE_LEAKING_OBJECT_PTR(X): the heap object referenced by pointer X will // be annotated as a leak. -#if defined(LEAK_SANITIZER) && !defined(OS_NACL) +#if defined(LEAK_SANITIZER) && !BUILDFLAG(IS_NACL) #include <sanitizer/lsan_interface.h>
diff --git a/base/macros.h b/base/macros.h deleted file mode 100644 index 19d15ca..0000000 --- a/base/macros.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright 2014 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. - -// This file contains macros and macro-like constructs (e.g., templates) that -// are commonly used throughout Chromium source. (It may also contain things -// that are closely related to things that are commonly used that belong in this -// file.) - -#ifndef BASE_MACROS_H_ -#define BASE_MACROS_H_ - -// ALL DISALLOW_xxx MACROS ARE DEPRECATED; DO NOT USE IN NEW CODE. -// Use explicit deletions instead. See the section on copyability/movability in -// //styleguide/c++/c++-dos-and-donts.md for more information. - -// DEPRECATED: See above. Makes a class uncopyable. -#define DISALLOW_COPY(TypeName) \ - TypeName(const TypeName&) = delete - -// DEPRECATED: See above. Makes a class unassignable. -#define DISALLOW_ASSIGN(TypeName) TypeName& operator=(const TypeName&) = delete - -// DEPRECATED: See above. Makes a class uncopyable and unassignable. -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ - DISALLOW_COPY(TypeName); \ - DISALLOW_ASSIGN(TypeName) - -// DEPRECATED: See above. Disallow all implicit constructors, namely the -// default constructor, copy constructor and operator= functions. -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ - TypeName() = delete; \ - DISALLOW_COPY_AND_ASSIGN(TypeName) - -// Used to explicitly mark the return value of a function as unused. If you are -// really sure you don't want to do anything with the return value of a function -// that has been marked WARN_UNUSED_RESULT, wrap it with this. Example: -// -// std::unique_ptr<MyType> my_var = ...; -// if (TakeOwnership(my_var.get()) == SUCCESS) -// ignore_result(my_var.release()); -// -template<typename T> -inline void ignore_result(const T&) { -} - -#endif // BASE_MACROS_H_
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h new file mode 100644 index 0000000..379c0d8 --- /dev/null +++ b/base/memory/raw_ptr.h
@@ -0,0 +1,910 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_MEMORY_RAW_PTR_H_ +#define BASE_MEMORY_RAW_PTR_H_ + +#include <stddef.h> +#include <stdint.h> + +#include <cstddef> +#include <functional> +#include <type_traits> +#include <utility> + +#include "polyfills/base/allocator/buildflags.h" +#include "polyfills/base/check.h" +#include "base/compiler_specific.h" +#include "polyfills/base/dcheck_is_on.h" +#include "build/build_config.h" +#include "build/buildflag.h" + +#if BUILDFLAG(USE_BACKUP_REF_PTR) +// USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under +// allocator/partition_allocator/ to be built. +#include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" +#include "base/allocator/partition_allocator/partition_address_space.h" +#include "base/allocator/partition_allocator/partition_alloc_config.h" +#include "base/allocator/partition_allocator/partition_alloc_constants.h" +#include "polyfills/base/base_export.h" +#endif // BUILDFLAG(USE_BACKUP_REF_PTR) + +#if BUILDFLAG(IS_WIN) +#include "base/win/windows_types.h" +#endif + +// Marks a field as excluded from the raw_ptr usage enforcement clang plugin. +// Example: RAW_PTR_EXCLUSION Foo* foo_; +#define RAW_PTR_EXCLUSION __attribute__((annotate("raw_ptr_exclusion"))) + +namespace cc { +class Scheduler; +} +namespace gurl_base::internal { +class DelayTimerBase; +} +namespace content::responsiveness { +class Calculator; +} + +namespace gurl_base { + +// NOTE: All methods should be `ALWAYS_INLINE NO_STACK_PROTECTOR`. +// ALWAYS_INLINE: raw_ptr is meant to be a lightweight replacement of a raw +// pointer, hence performance is critical. +// NO_STACK_PROTECTOR: This annotation is required to avoid failures when a +// raw_ptr is inside a NO_STACK_PROTECTOR function. +// TODO(https://crbug.com/1274129): Remove NO_STACK_PROTECTOR. +#define RAW_PTR_FUNC_ATTRIBUTES ALWAYS_INLINE NO_STACK_PROTECTOR + +namespace internal { +// These classes/structures are part of the raw_ptr implementation. +// DO NOT USE THESE CLASSES DIRECTLY YOURSELF. + +struct RawPtrNoOpImpl { + // Wraps a pointer. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T*) {} + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by |delta| bytes. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, + ptrdiff_t delta_elems) { + return wrapped_ptr + delta_elems; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + return wrapped_ptr; + } + + // This is for accounting only, used by unit tests. + static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} + static RAW_PTR_FUNC_ATTRIBUTES void + IncrementPointerToMemberOperatorCountForTest() {} +}; + +#if BUILDFLAG(USE_BACKUP_REF_PTR) + +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) +BASE_EXPORT void CheckThatAddressIsntWithinFirstPartitionPage( + uintptr_t address); +#endif + +struct BackupRefPtrImpl { + // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads + // modify the same smart pointer object without synchronization, a data race + // will occur. + + static RAW_PTR_FUNC_ATTRIBUTES bool IsSupportedAndNotNull(uintptr_t address) { + // This covers the nullptr case, as address 0 is never in GigaCage. + bool is_in_brp_pool = IsManagedByPartitionAllocBRPPool(address); + + // There are many situations where the compiler can prove that + // ReleaseWrappedPtr is called on a value that is always nullptr, but the + // way the check above is written, the compiler can't prove that nullptr is + // not managed by PartitionAlloc; and so the compiler has to emit a useless + // check and dead code. + // To avoid that without making the runtime check slower, explicitly promise + // to the compiler that is_in_brp_pool will always be false for nullptr. + // + // This condition would look nicer and might also theoretically be nicer for + // the optimizer if it was written as "if (!address) { ... }", but + // LLVM currently has issues with optimizing that away properly; see: + // https://bugs.llvm.org/show_bug.cgi?id=49403 + // https://reviews.llvm.org/D97848 + // https://chromium-review.googlesource.com/c/chromium/src/+/2727400/2/base/memory/checked_ptr.h#120 +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + GURL_CHECK(address || !is_in_brp_pool); +#endif +#if HAS_BUILTIN(__builtin_assume) + __builtin_assume(address || !is_in_brp_pool); +#endif + + // There may be pointers immediately after the allocation, e.g. + // { + // // Assume this allocation happens outside of PartitionAlloc. + // raw_ptr<T> ptr = new T[20]; + // for (size_t i = 0; i < 20; i ++) { ptr++; } + // } + // + // Such pointers are *not* at risk of accidentally falling into BRP pool, + // because: + // 1) On 64-bit systems, BRP pool is preceded by a forbidden region. + // 2) On 32-bit systems, the guard pages and metadata of super pages in BRP + // pool aren't considered to be part of that pool. + // + // This allows us to make a stronger assertion that if + // IsManagedByPartitionAllocBRPPool returns true for a valid pointer, + // it must be at least partition page away from the beginning of a super + // page. +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + if (is_in_brp_pool) { + CheckThatAddressIsntWithinFirstPartitionPage(address); + } +#endif + + return is_in_brp_pool; + } + + // Wraps a pointer. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + uintptr_t address = reinterpret_cast<uintptr_t>(ptr); + if (IsSupportedAndNotNull(address)) { +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + GURL_CHECK(ptr != nullptr); +#endif + AcquireInternal(address); + } +#if !defined(PA_HAS_64_BITS_POINTERS) + else { + AddressPoolManagerBitmap::BanSuperPageFromBRPPool(address); + } +#endif + + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T* wrapped_ptr) { + uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr); + if (IsSupportedAndNotNull(address)) { +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + GURL_CHECK(wrapped_ptr != nullptr); +#endif + ReleaseInternal(address); + } + // We are unable to counteract BanSuperPageFromBRPPool(), called from + // WrapRawPtr(). We only use one bit per super-page and, thus can't tell if + // there's more than one associated raw_ptr<T> at a given time. The risk of + // exhausting the entire address space is minuscule, therefore, we couldn't + // resist the perf gain of a single relaxed store (in the above mentioned + // function) over much more expensive two CAS operations, which we'd have to + // use if we were to un-ban a super-page. + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( + T* wrapped_ptr) { +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr); + if (IsSupportedAndNotNull(address)) { + GURL_CHECK(wrapped_ptr != nullptr); + GURL_CHECK(IsPointeeAlive(address)); + } +#endif + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by |delta| bytes. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, + ptrdiff_t delta_elem) { +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr); + if (IsSupportedAndNotNull(address)) + GURL_CHECK(IsValidDelta(address, delta_elem * sizeof(T))); +#endif + T* new_wrapped_ptr = WrapRawPtr(wrapped_ptr + delta_elem); + ReleaseWrappedPtr(wrapped_ptr); + return new_wrapped_ptr; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + // This method increments the reference count of the allocation slot. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + return WrapRawPtr(wrapped_ptr); + } + + // This is for accounting only, used by unit tests. + static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} + static RAW_PTR_FUNC_ATTRIBUTES void + IncrementPointerToMemberOperatorCountForTest() {} + + private: + // We've evaluated several strategies (inline nothing, various parts, or + // everything in |Wrap()| and |Release()|) using the Speedometer2 benchmark + // to measure performance. The best results were obtained when only the + // lightweight |IsManagedByPartitionAllocBRPPool()| check was inlined. + // Therefore, we've extracted the rest into the functions below and marked + // them as NOINLINE to prevent unintended LTO effects. + static BASE_EXPORT NOINLINE void AcquireInternal(uintptr_t address); + static BASE_EXPORT NOINLINE void ReleaseInternal(uintptr_t address); + static BASE_EXPORT NOINLINE bool IsPointeeAlive(uintptr_t address); + static BASE_EXPORT NOINLINE bool IsValidDelta(uintptr_t address, + ptrdiff_t delta_in_bytes); +}; + +#endif // BUILDFLAG(USE_BACKUP_REF_PTR) + +// Implementation that allows us to detect BackupRefPtr problems in ASan builds. +struct AsanBackupRefPtrImpl { + // Wraps a pointer. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + AsanCheckIfValidInstantiation(ptr); + return ptr; + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T*) {} + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function is allowed to crash on nullptr. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( + T* wrapped_ptr) { + AsanCheckIfValidDereference(wrapped_ptr); + return wrapped_ptr; + } + + // Unwraps the pointer, while asserting that memory hasn't been freed. The + // function must handle nullptr gracefully. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( + T* wrapped_ptr) { + AsanCheckIfValidExtraction(wrapped_ptr); + return wrapped_ptr; + } + + // Unwraps the pointer, without making an assertion on whether memory was + // freed or not. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( + T* wrapped_ptr) { + return wrapped_ptr; + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + // Note, this cast may change the address if upcasting to base that lies in + // the middle of the derived object. + return wrapped_ptr; + } + + // Advance the wrapped pointer by |delta| bytes. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, + ptrdiff_t delta_elems) { + return wrapped_ptr + delta_elems; + } + + // Returns a copy of a wrapped pointer, without making an assertion on whether + // memory was freed or not. + template <typename T> + static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + return wrapped_ptr; + } + + // This is for accounting only, used by unit tests. + static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} + static RAW_PTR_FUNC_ATTRIBUTES void + IncrementPointerToMemberOperatorCountForTest() {} + + private: + static BASE_EXPORT NOINLINE void AsanCheckIfValidInstantiation( + void const volatile* ptr); + static BASE_EXPORT NOINLINE void AsanCheckIfValidDereference( + void const volatile* ptr); + static BASE_EXPORT NOINLINE void AsanCheckIfValidExtraction( + void const volatile* ptr); +}; + +} // namespace internal + +namespace raw_ptr_traits { + +// IsSupportedType<T>::value answers whether raw_ptr<T> 1) compiles and 2) is +// always safe at runtime. Templates that may end up using `raw_ptr<T>` should +// use IsSupportedType to ensure that raw_ptr is not used with unsupported +// types. As an example, see how gurl_base::internal::StorageTraits uses +// IsSupportedType as a condition for using gurl_base::internal::UnretainedWrapper +// (which has a `ptr_` field that will become `raw_ptr<T>` after the Big +// Rewrite). +template <typename T, typename SFINAE = void> +struct IsSupportedType { + static constexpr bool value = true; +}; + +// raw_ptr<T> is not compatible with function pointer types. Also, they don't +// even need the raw_ptr protection, because they don't point on heap. +template <typename T> +struct IsSupportedType<T, std::enable_if_t<std::is_function<T>::value>> { + static constexpr bool value = false; +}; + +// This section excludes some types from raw_ptr<T> to avoid them from being +// used inside gurl_base::Unretained in performance sensitive places. These were +// identified from sampling profiler data. See crbug.com/1287151 for more info. +template <> +struct IsSupportedType<cc::Scheduler> { + static constexpr bool value = false; +}; +template <> +struct IsSupportedType<gurl_base::internal::DelayTimerBase> { + static constexpr bool value = false; +}; +template <> +struct IsSupportedType<content::responsiveness::Calculator> { + static constexpr bool value = false; +}; + +#if __OBJC__ +// raw_ptr<T> is not compatible with pointers to Objective-C classes for a +// multitude of reasons. They may fail to compile in many cases, and wouldn't +// work well with tagged pointers. Anyway, Objective-C objects have their own +// way of tracking lifespan, hence don't need the raw_ptr protection as much. +// +// Such pointers are detected by checking if they're convertible to |id| type. +template <typename T> +struct IsSupportedType<T, + std::enable_if_t<std::is_convertible<T*, id>::value>> { + static constexpr bool value = false; +}; +#endif // __OBJC__ + +#if BUILDFLAG(IS_WIN) +// raw_ptr<HWND__> is unsafe at runtime - if the handle happens to also +// represent a valid pointer into a PartitionAlloc-managed region then it can +// lead to manipulating random memory when treating it as BackupRefPtr +// ref-count. See also https://crbug.com/1262017. +// +// TODO(https://crbug.com/1262017): Cover other handle types like HANDLE, +// HLOCAL, HINTERNET, or HDEVINFO. Maybe we should avoid using raw_ptr<T> when +// T=void (as is the case in these handle types). OTOH, explicit, +// non-template-based raw_ptr<void> should be allowed. Maybe this can be solved +// by having 2 traits: IsPointeeAlwaysSafe (to be used in templates) and +// IsPointeeUsuallySafe (to be used in the static_assert in raw_ptr). The +// upside of this approach is that it will safely handle gurl_base::Bind closing over +// HANDLE. The downside of this approach is that gurl_base::Bind closing over a +// void* pointer will not get UaF protection. +#define CHROME_WINDOWS_HANDLE_TYPE(name) \ + template <> \ + struct IsSupportedType<name##__, void> { \ + static constexpr bool value = false; \ + }; +#include "base/win/win_handle_types_list.inc" +#undef CHROME_WINDOWS_HANDLE_TYPE +#endif + +} // namespace raw_ptr_traits + +// `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety +// over raw pointers. It behaves just like a raw pointer on platforms where +// USE_BACKUP_REF_PTR is off, and almost like one when it's on (the main +// difference is that it's zero-initialized and cleared on destruction and +// move). Unlike `std::unique_ptr<T>`, `gurl_base::scoped_refptr<T>`, etc., it +// doesn’t manage ownership or lifetime of an allocated object - you are still +// responsible for freeing the object when no longer used, just as you would +// with a raw C++ pointer. +// +// Compared to a raw C++ pointer, on platforms where USE_BACKUP_REF_PTR is on, +// `raw_ptr<T>` incurs additional performance overhead for initialization, +// destruction, and assignment (including `ptr++` and `ptr += ...`). There is +// no overhead when dereferencing a pointer. +// +// `raw_ptr<T>` is beneficial for security, because it can prevent a significant +// percentage of Use-after-Free (UaF) bugs from being exploitable. `raw_ptr<T>` +// has limited impact on stability - dereferencing a dangling pointer remains +// Undefined Behavior. Note that the security protection is not yet enabled by +// default. +// +// raw_ptr<T> is marked as [[gsl::Pointer]] which allows the compiler to catch +// some bugs where the raw_ptr holds a dangling pointer to a temporary object. +// However the [[gsl::Pointer]] analysis expects that such types do not have a +// non-default move constructor/assignment. Thus, it's possible to get an error +// where the pointer is not actually dangling, and have to work around the +// compiler. We have not managed to construct such an example in Chromium yet. +template <typename T, +#if BUILDFLAG(USE_BACKUP_REF_PTR) + typename Impl = internal::BackupRefPtrImpl> +#elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) + typename Impl = internal::AsanBackupRefPtrImpl> +#else + typename Impl = internal::RawPtrNoOpImpl> +#endif +class TRIVIAL_ABI GSL_POINTER raw_ptr { + public: + static_assert(raw_ptr_traits::IsSupportedType<T>::value, + "raw_ptr<T> doesn't work with this kind of pointee type T"); + +#if BUILDFLAG(USE_BACKUP_REF_PTR) + // BackupRefPtr requires a non-trivial default constructor, destructor, etc. + constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr() noexcept + : wrapped_ptr_(nullptr) {} + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr& p) noexcept + : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {} + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr&& p) noexcept { + wrapped_ptr_ = p.wrapped_ptr_; + p.wrapped_ptr_ = nullptr; + } + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(const raw_ptr& p) { + // Duplicate before releasing, in case the pointer is assigned to itself. + T* new_ptr = Impl::Duplicate(p.wrapped_ptr_); + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = new_ptr; + return *this; + } + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr&& p) { + if (LIKELY(this != &p)) { + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = p.wrapped_ptr_; + p.wrapped_ptr_ = nullptr; + } + return *this; + } + + RAW_PTR_FUNC_ATTRIBUTES ~raw_ptr() noexcept { + Impl::ReleaseWrappedPtr(wrapped_ptr_); + // Work around external issues where raw_ptr is used after destruction. + wrapped_ptr_ = nullptr; + } + +#else // BUILDFLAG(USE_BACKUP_REF_PTR) + + // raw_ptr can be trivially default constructed (leaving |wrapped_ptr_| + // uninitialized). This is needed for compatibility with raw pointers. + // + // TODO(lukasza): Always initialize |wrapped_ptr_|. Fix resulting build + // errors. Analyze performance impact. + constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr() noexcept = default; + + // In addition to nullptr_t ctor above, raw_ptr needs to have these + // as |=default| or |constexpr| to avoid hitting -Wglobal-constructors in + // cases like this: + // struct SomeStruct { int int_field; raw_ptr<int> ptr_field; }; + // SomeStruct g_global_var = { 123, nullptr }; + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr&) noexcept = default; + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr&&) noexcept = default; + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(const raw_ptr&) noexcept = default; + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr&&) noexcept = default; + + RAW_PTR_FUNC_ATTRIBUTES ~raw_ptr() = default; + +#endif // BUILDFLAG(USE_BACKUP_REF_PTR) + + // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. + // NOLINTNEXTLINE(google-explicit-constructor) + constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr(std::nullptr_t) noexcept + : wrapped_ptr_(nullptr) {} + + // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. + // NOLINTNEXTLINE(google-explicit-constructor) + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(T* p) noexcept + : wrapped_ptr_(Impl::WrapRawPtr(p)) {} + + // Deliberately implicit in order to support implicit upcast. + template <typename U, + typename Unused = std::enable_if_t< + std::is_convertible<U*, T*>::value && + !std::is_void<typename std::remove_cv<T>::type>::value>> + // NOLINTNEXTLINE(google-explicit-constructor) + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr<U, Impl>& ptr) noexcept + : wrapped_ptr_( + Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {} + // Deliberately implicit in order to support implicit upcast. + template <typename U, + typename Unused = std::enable_if_t< + std::is_convertible<U*, T*>::value && + !std::is_void<typename std::remove_cv<T>::type>::value>> + // NOLINTNEXTLINE(google-explicit-constructor) + RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr<U, Impl>&& ptr) noexcept + : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) { +#if BUILDFLAG(USE_BACKUP_REF_PTR) + ptr.wrapped_ptr_ = nullptr; +#endif + } + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(std::nullptr_t) noexcept { + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = nullptr; + return *this; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(T* p) noexcept { + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = Impl::WrapRawPtr(p); + return *this; + } + + // Upcast assignment + template <typename U, + typename Unused = std::enable_if_t< + std::is_convertible<U*, T*>::value && + !std::is_void<typename std::remove_cv<T>::type>::value>> + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=( + const raw_ptr<U, Impl>& ptr) noexcept { + // Make sure that pointer isn't assigned to itself (look at pointer address, + // not its value). +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + GURL_CHECK(reinterpret_cast<uintptr_t>(this) != + reinterpret_cast<uintptr_t>(&ptr)); +#endif + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = + Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)); + return *this; + } + template <typename U, + typename Unused = std::enable_if_t< + std::is_convertible<U*, T*>::value && + !std::is_void<typename std::remove_cv<T>::type>::value>> + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr<U, Impl>&& ptr) noexcept { + // Make sure that pointer isn't assigned to itself (look at pointer address, + // not its value). +#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) + GURL_CHECK(reinterpret_cast<uintptr_t>(this) != + reinterpret_cast<uintptr_t>(&ptr)); +#endif + Impl::ReleaseWrappedPtr(wrapped_ptr_); + wrapped_ptr_ = Impl::template Upcast<T, U>(ptr.wrapped_ptr_); +#if BUILDFLAG(USE_BACKUP_REF_PTR) + ptr.wrapped_ptr_ = nullptr; +#endif + return *this; + } + + // Avoid using. The goal of raw_ptr is to be as close to raw pointer as + // possible, so use it only if absolutely necessary (e.g. for const_cast). + RAW_PTR_FUNC_ATTRIBUTES T* get() const { return GetForExtraction(); } + + explicit RAW_PTR_FUNC_ATTRIBUTES operator bool() const { + return !!wrapped_ptr_; + } + + template <typename U = T, + typename Unused = std::enable_if_t< + !std::is_void<typename std::remove_cv<U>::type>::value>> + RAW_PTR_FUNC_ATTRIBUTES U& operator*() const { + return *GetForDereference(); + } + RAW_PTR_FUNC_ATTRIBUTES T* operator->() const { return GetForDereference(); } + + // Disables `(my_raw_ptr->*pmf)(...)` as a workaround for + // the ICE in GCC parsing the code, reported at + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103455 + template <typename PMF> + void operator->*(PMF) const = delete; + + // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. + // NOLINTNEXTLINE(runtime/explicit) + RAW_PTR_FUNC_ATTRIBUTES operator T*() const { return GetForExtraction(); } + template <typename U> + explicit RAW_PTR_FUNC_ATTRIBUTES operator U*() const { + // This operator may be invoked from static_cast, meaning the types may not + // be implicitly convertible, hence the need for static_cast here. + return static_cast<U*>(GetForExtraction()); + } + + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator++() { + wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1); + return *this; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator--() { + wrapped_ptr_ = Impl::Advance(wrapped_ptr_, -1); + return *this; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr operator++(int /* post_increment */) { + raw_ptr result = *this; + ++(*this); + return result; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr operator--(int /* post_decrement */) { + raw_ptr result = *this; + --(*this); + return result; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator+=(ptrdiff_t delta_elems) { + wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems); + return *this; + } + RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator-=(ptrdiff_t delta_elems) { + return *this += -delta_elems; + } + + // Stop referencing the underlying pointer and free its memory. Compared to + // raw delete calls, this avoids the raw_ptr to be temporarily dangling + // during the free operation, which will lead to taking the slower path that + // involves quarantine. + RAW_PTR_FUNC_ATTRIBUTES void ClearAndDelete() noexcept { + T* ptr = wrapped_ptr_; + operator=(nullptr); + delete ptr; + } + RAW_PTR_FUNC_ATTRIBUTES void ClearAndDeleteArray() noexcept { + T* ptr = wrapped_ptr_; + operator=(nullptr); + delete[] ptr; + } + + // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t. + // Strictly speaking, it is not necessary to provide these: the compiler can + // use the conversion operator implicitly to allow comparisons to fall back to + // comparisons between raw pointers. However, `operator T*`/`operator U*` may + // perform safety checks with a higher runtime cost, so to avoid this, provide + // explicit comparison operators for all combinations of parameters. + + // Comparisons between `raw_ptr`s. This unusual declaration and separate + // definition below is because `GetForComparison()` is a private method. The + // more conventional approach of defining a comparison operator between + // `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work, + // because a comparison operator defined inline would not be allowed to call + // `raw_ptr<U>`'s private `GetForComparison()` method. + template <typename U, typename V, typename I> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, + const raw_ptr<U, Impl>& rhs) { + return !(lhs == rhs); + } + template <typename U, typename V, typename I> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); + template <typename U, typename V, typename I> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); + template <typename U, typename V, typename I> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); + template <typename U, typename V, typename I> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); + + // Comparisons with U*. These operators also handle the case where the RHS is + // T*. + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr& lhs, U* rhs) { + return lhs.GetForComparison() == rhs; + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, U* rhs) { + return !(lhs == rhs); + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(U* lhs, const raw_ptr& rhs) { + return rhs == lhs; // Reverse order to call the operator above. + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(U* lhs, const raw_ptr& rhs) { + return rhs != lhs; // Reverse order to call the operator above. + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr& lhs, U* rhs) { + return lhs.GetForComparison() < rhs; + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr& lhs, U* rhs) { + return lhs.GetForComparison() <= rhs; + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr& lhs, U* rhs) { + return lhs.GetForComparison() > rhs; + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr& lhs, U* rhs) { + return lhs.GetForComparison() >= rhs; + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(U* lhs, const raw_ptr& rhs) { + return lhs < rhs.GetForComparison(); + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(U* lhs, const raw_ptr& rhs) { + return lhs <= rhs.GetForComparison(); + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(U* lhs, const raw_ptr& rhs) { + return lhs > rhs.GetForComparison(); + } + template <typename U> + friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(U* lhs, const raw_ptr& rhs) { + return lhs >= rhs.GetForComparison(); + } + + // Comparisons with `std::nullptr_t`. + friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr& lhs, + std::nullptr_t) { + return !lhs; + } + friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, + std::nullptr_t) { + return !!lhs; // Use !! otherwise the costly implicit cast will be used. + } + friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(std::nullptr_t, + const raw_ptr& rhs) { + return !rhs; + } + friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(std::nullptr_t, + const raw_ptr& rhs) { + return !!rhs; // Use !! otherwise the costly implicit cast will be used. + } + + friend RAW_PTR_FUNC_ATTRIBUTES void swap(raw_ptr& lhs, + raw_ptr& rhs) noexcept { + Impl::IncrementSwapCountForTest(); + std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_); + } + + private: + // This getter is meant for situations where the pointer is meant to be + // dereferenced. It is allowed to crash on nullptr (it may or may not), + // because it knows that the caller will crash on nullptr. + RAW_PTR_FUNC_ATTRIBUTES T* GetForDereference() const { + return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_); + } + // This getter is meant for situations where the raw pointer is meant to be + // extracted outside of this class, but not necessarily with an intention to + // dereference. It mustn't crash on nullptr. + RAW_PTR_FUNC_ATTRIBUTES T* GetForExtraction() const { + return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_); + } + // This getter is meant *only* for situations where the pointer is meant to be + // compared (guaranteeing no dereference or extraction outside of this class). + // Any verifications can and should be skipped for performance reasons. + RAW_PTR_FUNC_ATTRIBUTES T* GetForComparison() const { + return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_); + } + + T* wrapped_ptr_; + + template <typename U, typename V> + friend class raw_ptr; +}; + +template <typename U, typename V, typename I> +RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { + return lhs.GetForComparison() == rhs.GetForComparison(); +} + +template <typename U, typename V, typename I> +RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { + return lhs.GetForComparison() < rhs.GetForComparison(); +} + +template <typename U, typename V, typename I> +RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { + return lhs.GetForComparison() > rhs.GetForComparison(); +} + +template <typename U, typename V, typename I> +RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { + return lhs.GetForComparison() <= rhs.GetForComparison(); +} + +template <typename U, typename V, typename I> +RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { + return lhs.GetForComparison() >= rhs.GetForComparison(); +} + +} // namespace base + +using gurl_base::raw_ptr; + +namespace std { + +// Override so set/map lookups do not create extra raw_ptr. This also allows +// dangling pointers to be used for lookup. +template <typename T, typename I> +struct less<raw_ptr<T, I>> { + using is_transparent = void; + + bool operator()(const raw_ptr<T, I>& lhs, const raw_ptr<T, I>& rhs) const { + return lhs < rhs; + } + + bool operator()(T* lhs, const raw_ptr<T, I>& rhs) const { return lhs < rhs; } + + bool operator()(const raw_ptr<T, I>& lhs, T* rhs) const { return lhs < rhs; } +}; + +} // namespace std + +#endif // BASE_MEMORY_RAW_PTR_H_
diff --git a/base/stl_util.h b/base/stl_util.h index 46e91b9..a9c627d 100644 --- a/base/stl_util.h +++ b/base/stl_util.h
@@ -10,9 +10,7 @@ #include <algorithm> #include <forward_list> #include <iterator> -#include <tuple> #include <type_traits> -#include <utility> #include "polyfills/base/check.h" #include "base/ranges/algorithm.h" @@ -111,166 +109,6 @@ return begin(c) + (it - cbegin(c)); } -namespace internal { - -template <typename Map, typename Key, typename Value> -std::pair<typename Map::iterator, bool> InsertOrAssignImpl(Map& map, - Key&& key, - Value&& value) { - auto lower = map.lower_bound(key); - if (lower != map.end() && !map.key_comp()(key, lower->first)) { - // key already exists, perform assignment. - lower->second = std::forward<Value>(value); - return {lower, false}; - } - - // key did not yet exist, insert it. - return {map.emplace_hint(lower, std::forward<Key>(key), - std::forward<Value>(value)), - true}; -} - -template <typename Map, typename Key, typename Value> -typename Map::iterator InsertOrAssignImpl(Map& map, - typename Map::const_iterator hint, - Key&& key, - Value&& value) { - auto&& key_comp = map.key_comp(); - if ((hint == map.begin() || key_comp(std::prev(hint)->first, key))) { - if (hint == map.end() || key_comp(key, hint->first)) { - // *(hint - 1) < key < *hint => key did not exist and hint is correct. - return map.emplace_hint(hint, std::forward<Key>(key), - std::forward<Value>(value)); - } - - if (!key_comp(hint->first, key)) { - // key == *hint => key already exists and hint is correct. - auto mutable_hint = ConstCastIterator(map, hint); - mutable_hint->second = std::forward<Value>(value); - return mutable_hint; - } - } - - // hint was not helpful, dispatch to hintless version. - return InsertOrAssignImpl(map, std::forward<Key>(key), - std::forward<Value>(value)) - .first; -} - -template <typename Map, typename Key, typename... Args> -std::pair<typename Map::iterator, bool> TryEmplaceImpl(Map& map, - Key&& key, - Args&&... args) { - auto lower = map.lower_bound(key); - if (lower != map.end() && !map.key_comp()(key, lower->first)) { - // key already exists, do nothing. - return {lower, false}; - } - - // key did not yet exist, insert it. - return {map.emplace_hint(lower, std::piecewise_construct, - std::forward_as_tuple(std::forward<Key>(key)), - std::forward_as_tuple(std::forward<Args>(args)...)), - true}; -} - -template <typename Map, typename Key, typename... Args> -typename Map::iterator TryEmplaceImpl(Map& map, - typename Map::const_iterator hint, - Key&& key, - Args&&... args) { - auto&& key_comp = map.key_comp(); - if ((hint == map.begin() || key_comp(std::prev(hint)->first, key))) { - if (hint == map.end() || key_comp(key, hint->first)) { - // *(hint - 1) < key < *hint => key did not exist and hint is correct. - return map.emplace_hint( - hint, std::piecewise_construct, - std::forward_as_tuple(std::forward<Key>(key)), - std::forward_as_tuple(std::forward<Args>(args)...)); - } - - if (!key_comp(hint->first, key)) { - // key == *hint => no-op, return correct hint. - return ConstCastIterator(map, hint); - } - } - - // hint was not helpful, dispatch to hintless version. - return TryEmplaceImpl(map, std::forward<Key>(key), - std::forward<Args>(args)...) - .first; -} - -} // namespace internal - -// Implementation of C++17's std::map::insert_or_assign as a free function. -template <typename Map, typename Value> -std::pair<typename Map::iterator, bool> -InsertOrAssign(Map& map, const typename Map::key_type& key, Value&& value) { - return internal::InsertOrAssignImpl(map, key, std::forward<Value>(value)); -} - -template <typename Map, typename Value> -std::pair<typename Map::iterator, bool> -InsertOrAssign(Map& map, typename Map::key_type&& key, Value&& value) { - return internal::InsertOrAssignImpl(map, std::move(key), - std::forward<Value>(value)); -} - -// Implementation of C++17's std::map::insert_or_assign with hint as a free -// function. -template <typename Map, typename Value> -typename Map::iterator InsertOrAssign(Map& map, - typename Map::const_iterator hint, - const typename Map::key_type& key, - Value&& value) { - return internal::InsertOrAssignImpl(map, hint, key, - std::forward<Value>(value)); -} - -template <typename Map, typename Value> -typename Map::iterator InsertOrAssign(Map& map, - typename Map::const_iterator hint, - typename Map::key_type&& key, - Value&& value) { - return internal::InsertOrAssignImpl(map, hint, std::move(key), - std::forward<Value>(value)); -} - -// Implementation of C++17's std::map::try_emplace as a free function. -template <typename Map, typename... Args> -std::pair<typename Map::iterator, bool> -TryEmplace(Map& map, const typename Map::key_type& key, Args&&... args) { - return internal::TryEmplaceImpl(map, key, std::forward<Args>(args)...); -} - -template <typename Map, typename... Args> -std::pair<typename Map::iterator, bool> TryEmplace(Map& map, - typename Map::key_type&& key, - Args&&... args) { - return internal::TryEmplaceImpl(map, std::move(key), - std::forward<Args>(args)...); -} - -// Implementation of C++17's std::map::try_emplace with hint as a free -// function. -template <typename Map, typename... Args> -typename Map::iterator TryEmplace(Map& map, - typename Map::const_iterator hint, - const typename Map::key_type& key, - Args&&... args) { - return internal::TryEmplaceImpl(map, hint, key, std::forward<Args>(args)...); -} - -template <typename Map, typename... Args> -typename Map::iterator TryEmplace(Map& map, - typename Map::const_iterator hint, - typename Map::key_type&& key, - Args&&... args) { - return internal::TryEmplaceImpl(map, hint, std::move(key), - std::forward<Args>(args)...); -} - // Returns a new ResultType containing the difference of two sorted containers. template <typename ResultType, typename Arg1, typename Arg2> ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
diff --git a/base/strings/BUILD b/base/strings/BUILD deleted file mode 100644 index 257f8f9..0000000 --- a/base/strings/BUILD +++ /dev/null
@@ -1,33 +0,0 @@ -# Copyright 2019 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. -load("//build_config:build_config.bzl", "build_config") -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "strings", - srcs = [ - "string_piece.cc", - "string_util.cc", - "string_util_constants.cc", - "utf_string_conversion_utils.cc", - "utf_string_conversions.cc", - ], - hdrs = [ - "char_traits.h", - "string_piece_forward.h", - "string_piece.h", - "string_util.h", - "string_util_internal.h", - "utf_string_conversions.h", - "utf_string_conversion_utils.h", - ] + build_config.strings_hdrs, - copts = build_config.default_copts, - visibility = ["//visibility:public"], - deps = [ - "//base", - "//base/third_party/icu", - "//build:build_config", - "//polyfills", - ], -)
diff --git a/base/strings/abseil_string_number_conversions.cc b/base/strings/abseil_string_number_conversions.cc new file mode 100644 index 0000000..9ab1303 --- /dev/null +++ b/base/strings/abseil_string_number_conversions.cc
@@ -0,0 +1,17 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/abseil_string_number_conversions.h" + +#include "base/strings/string_number_conversions_internal.h" +#include "base/strings/string_piece.h" +#include "absl/numeric/int128.h" + +namespace gurl_base { + +bool HexStringToUInt128(StringPiece input, absl::uint128* output) { + return internal::HexStringToIntImpl(input, *output); +} + +} // namespace base
diff --git a/base/strings/abseil_string_number_conversions.h b/base/strings/abseil_string_number_conversions.h new file mode 100644 index 0000000..7eb927d --- /dev/null +++ b/base/strings/abseil_string_number_conversions.h
@@ -0,0 +1,24 @@ +// Copyright 2022 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 BASE_STRINGS_ABSEIL_STRING_NUMBER_CONVERSIONS_H_ +#define BASE_STRINGS_ABSEIL_STRING_NUMBER_CONVERSIONS_H_ + +#include "polyfills/base/base_export.h" +#include "base/strings/string_piece_forward.h" + +namespace absl { +class uint128; +} // namespace absl + +namespace gurl_base { + +// Best effort conversion, see `gurl_base::StringToInt()` for restrictions. +// Will only successfully parse hex values that will fit into |output|. +// The string is not required to start with 0x. +BASE_EXPORT bool HexStringToUInt128(StringPiece input, absl::uint128* output); + +} // namespace base + +#endif // BASE_STRINGS_ABSEIL_STRING_NUMBER_CONVERSIONS_H_
diff --git a/base/strings/abseil_string_number_conversions_unittest.cc b/base/strings/abseil_string_number_conversions_unittest.cc new file mode 100644 index 0000000..3c68cde --- /dev/null +++ b/base/strings/abseil_string_number_conversions_unittest.cc
@@ -0,0 +1,102 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/abseil_string_number_conversions.h" + +#include <stdint.h> + +#include <limits> + +#include "base/cxx17_backports.h" +#include "base/strings/string_piece.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "absl/numeric/int128.h" + +namespace gurl_base { + +TEST(AbseilStringNumberConversionsTest, HexStringToUInt128) { + // Test cases adapted from `StringNumberConversionsTest.HexStringToUint64`. + static const struct { + std::string input; + absl::uint128 output; + bool success; + } cases[] = { + {"0", 0, true}, + {"42", 66, true}, + {"-42", 0, false}, + {"+42", 66, true}, + {"ffffffffffffffff", + absl::MakeUint128(/*high=*/0, + /*low=*/std::numeric_limits<uint64_t>::max()), + true}, + {"1ffffffffffffffff", + absl::MakeUint128(/*high=*/1, + /*low=*/std::numeric_limits<uint64_t>::max()), + true}, + {"7fffffff", INT_MAX, true}, + {"-80000000", 0, false}, + {"ffffffff", 0xffffffff, true}, + {"DeadBeef", 0xdeadbeef, true}, + {"0x42", 66, true}, + {"-0x42", 0, false}, + {"+0x42", 66, true}, + {"0xffffffffffffffff", + absl::MakeUint128(/*high=*/0, + /*low=*/std::numeric_limits<uint64_t>::max()), + true}, + {"0x1ffffffffffffffff", + absl::MakeUint128(/*high=*/1, + /*low=*/std::numeric_limits<uint64_t>::max()), + true}, + {"0x7fffffff", INT_MAX, true}, + {"-0x80000000", 0, false}, + {"0xffffffff", 0xffffffff, true}, + {"0XDeadBeef", 0xdeadbeef, true}, + {"0x7fffffffffffffffffffffffffffffff", + std::numeric_limits<absl::int128>::max(), true}, + {"-0x8000000000000000", 0, false}, + {"0x8000000000000000", + absl::MakeUint128(/*high=*/0, UINT64_C(0x8000000000000000)), true}, + {"-0x8000000000000001", 0, false}, + {"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + std::numeric_limits<absl::uint128>::max(), true}, + {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + std::numeric_limits<absl::uint128>::max(), true}, + {"0x0000000000000000", 0, true}, + {"0000000000000000", 0, true}, + {"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + std::numeric_limits<absl::uint128>::max(), false}, // Overflow test. + {"0x0f", 15, true}, + {"0f", 15, true}, + {" 45", 0x45, false}, + {"\t\n\v\f\r 0x45", 0x45, false}, + {" 45", 0x45, false}, + {"45 ", 0x45, false}, + {"45:", 0x45, false}, + {"efgh", 0xef, false}, + {"0xefgh", 0xef, false}, + {"hgfe", 0, false}, + {"-", 0, false}, + {"", 0, false}, + {"0x", 0, false}, + }; + + for (const auto& i : cases) { + absl::uint128 output = 0; + EXPECT_EQ(i.success, HexStringToUInt128(i.input, &output)) << i.input; + EXPECT_EQ(i.output, output) << i.input; + } + // One additional test to verify that conversion of numbers in strings with + // embedded NUL characters. The NUL and extra data after it should be + // interpreted as junk after the number. + const char input[] = + "0xc0ffee\0" + "9"; + std::string input_string(input, gurl_base::size(input) - 1); + absl::uint128 output; + EXPECT_FALSE(HexStringToUInt128(input_string, &output)); + EXPECT_EQ(0xc0ffeeU, output); +} + +} // namespace base
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc index c9a69ec..6c9aa19 100644 --- a/base/strings/safe_sprintf.cc +++ b/base/strings/safe_sprintf.cc
@@ -10,7 +10,7 @@ #include <algorithm> #include <limits> -#include "base/macros.h" +#include "base/memory/raw_ptr.h" #include "build/build_config.h" #if !defined(NDEBUG) @@ -117,7 +117,7 @@ // MSVS2013's standard library doesn't mark max() as constexpr yet. cl.exe // supports static_cast but doesn't really implement constexpr yet so it doesn't // complain, but clang does. -#if __cplusplus >= 201103 && !(defined(__clang__) && defined(OS_WIN)) +#if __cplusplus >= 201103 && !(defined(__clang__) && BUILDFLAG(IS_WIN)) static_assert(kSSizeMaxConst == static_cast<size_t>(std::numeric_limits<ssize_t>::max()), "kSSizeMaxConst should be the max value of an ssize_t"); @@ -263,7 +263,7 @@ } // User-provided buffer that will receive the fully formatted output string. - char* buffer_; + raw_ptr<char> buffer_; // Number of bytes that are available in the buffer excluding the trailing // NUL byte that will be added by the destructor.
diff --git a/base/strings/safe_sprintf.h b/base/strings/safe_sprintf.h index 40cddc5..478275e 100644 --- a/base/strings/safe_sprintf.h +++ b/base/strings/safe_sprintf.h
@@ -11,7 +11,7 @@ #include "build/build_config.h" -#if defined(OS_POSIX) || defined(OS_FUCHSIA) +#if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) // For ssize_t #include <unistd.h> #endif
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc index be8af13..71814b3 100644 --- a/base/strings/safe_sprintf_unittest.cc +++ b/base/strings/safe_sprintf_unittest.cc
@@ -13,14 +13,13 @@ #include <memory> #include "polyfills/base/check_op.h" -#include "base/macros.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" // Death tests on Android are currently very flaky. No need to add more flaky // tests, as they just make it hard to spot real problems. // TODO(markus): See if the restrictions on Android can eventually be lifted. -#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID) +#if defined(GTEST_HAS_DEATH_TEST) && !BUILDFLAG(IS_ANDROID) #define ALLOW_DEATH_TEST #endif
diff --git a/base/strings/strcat.h b/base/strings/strcat.h index fe35447..1cdd708 100644 --- a/base/strings/strcat.h +++ b/base/strings/strcat.h
@@ -8,12 +8,11 @@ #include <initializer_list> #include "polyfills/base/base_export.h" -#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/strings/string_piece.h" #include "build/build_config.h" -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) // Guard against conflict with Win32 API StrCat macro: // check StrCat wasn't and will not be redefined. #define StrCat StrCat @@ -59,14 +58,12 @@ // for this call and generate slightly less code. This is something we can // explore more in the future. -BASE_EXPORT std::string StrCat(span<const StringPiece> pieces) - WARN_UNUSED_RESULT; -BASE_EXPORT std::u16string StrCat(span<const StringPiece16> pieces) - WARN_UNUSED_RESULT; -BASE_EXPORT std::string StrCat(span<const std::string> pieces) - WARN_UNUSED_RESULT; -BASE_EXPORT std::u16string StrCat(span<const std::u16string> pieces) - WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string StrCat(span<const StringPiece> pieces); +[[nodiscard]] BASE_EXPORT std::u16string StrCat( + span<const StringPiece16> pieces); +[[nodiscard]] BASE_EXPORT std::string StrCat(span<const std::string> pieces); +[[nodiscard]] BASE_EXPORT std::u16string StrCat( + span<const std::u16string> pieces); // Initializer list forwards to the array version. inline std::string StrCat(std::initializer_list<StringPiece> pieces) { @@ -105,7 +102,7 @@ } // namespace base -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) #include "base/strings/strcat_win.h" #endif
diff --git a/base/strings/strcat_win.h b/base/strings/strcat_win.h index 70926bc..e32a7e5 100644 --- a/base/strings/strcat_win.h +++ b/base/strings/strcat_win.h
@@ -9,7 +9,6 @@ #include <string> #include "polyfills/base/base_export.h" -#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/strings/string_piece.h" @@ -25,10 +24,8 @@ StrAppend(dest, make_span(pieces)); } -BASE_EXPORT std::wstring StrCat(span<const WStringPiece> pieces) - WARN_UNUSED_RESULT; -BASE_EXPORT std::wstring StrCat(span<const std::wstring> pieces) - WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring StrCat(span<const WStringPiece> pieces); +[[nodiscard]] BASE_EXPORT std::wstring StrCat(span<const std::wstring> pieces); inline std::wstring StrCat(std::initializer_list<WStringPiece> pieces) { return StrCat(make_span(pieces));
diff --git a/base/strings/string_number_conversions.h b/base/strings/string_number_conversions.h index d2f8af3..1ef1733 100644 --- a/base/strings/string_number_conversions.h +++ b/base/strings/string_number_conversions.h
@@ -149,7 +149,7 @@ } // namespace base -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) #include "base/strings/string_number_conversions_win.h" #endif
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index f01722d..8d7f2c5 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -31,6 +31,7 @@ #include "polyfills/base/base_export.h" #include "polyfills/base/check_op.h" +#include "base/compiler_specific.h" #include "base/strings/char_traits.h" #include "base/strings/string_piece_forward.h" #include "build/build_config.h" @@ -96,7 +97,7 @@ // Mirrors the C++17 version of std::basic_string_view<> as closely as possible, // except where noted below. template <typename CharT, typename Traits> -class BasicStringPiece { +class GSL_POINTER BasicStringPiece { public: using traits_type = Traits; using value_type = CharT; @@ -185,9 +186,7 @@ return std::numeric_limits<size_type>::max() / sizeof(CharT); } - constexpr bool empty() const noexcept WARN_UNUSED_RESULT { - return size() == 0; - } + [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; } constexpr void remove_prefix(size_type n) { // Intentional STL deviation: Bounds-check instead of UB.
diff --git a/base/strings/string_piece_forward.h b/base/strings/string_piece_forward.h index ce7e489..e257528 100644 --- a/base/strings/string_piece_forward.h +++ b/base/strings/string_piece_forward.h
@@ -7,7 +7,7 @@ #ifndef BASE_STRINGS_STRING_PIECE_FORWARD_H_ #define BASE_STRINGS_STRING_PIECE_FORWARD_H_ -#include <string> +#include <iosfwd> namespace gurl_base {
diff --git a/base/strings/string_piece_rust.h b/base/strings/string_piece_rust.h new file mode 100644 index 0000000..1542c17 --- /dev/null +++ b/base/strings/string_piece_rust.h
@@ -0,0 +1,38 @@ +// Copyright 2021 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 BASE_STRINGS_STRING_PIECE_RUST_H_ +#define BASE_STRINGS_STRING_PIECE_RUST_H_ + +#include <stdint.h> + +#include "base/strings/string_piece.h" +#include "third_party/rust/cxx/v1/crate/include/cxx.h" + +namespace gurl_base { + +// Create a Rust str from a gurl_base::BasicStringPiece. This will call std::abort +// if there is any invalid UTF8. If you're concerned about this, then +// instead use StringPieceToRustSlice and convert the data to a string on +// the Rust side (or pass in a std::string). +inline rust::Str StringPieceToRustStrUTF8(StringPiece string_piece) { + return rust::Str(string_piece.data(), string_piece.size()); +} + +// Create a Rust slice from a StringPiece. No UTF8 check is performed. +inline rust::Slice<const uint8_t> StringPieceToRustSlice( + StringPiece string_piece) { + return rust::Slice<const uint8_t>( + reinterpret_cast<const uint8_t*>(string_piece.data()), + string_piece.length() * sizeof(StringPiece::value_type)); +} + +// Create a StringPiece from a Rust str. +inline StringPiece RustStrToStringPiece(rust::Str str) { + return StringPiece(str.data(), str.size()); +} + +} // namespace base + +#endif // BASE_STRINGS_STRING_PIECE_RUST_H_
diff --git a/base/strings/string_piece_rust_unittest.cc b/base/strings/string_piece_rust_unittest.cc new file mode 100644 index 0000000..bf860fb --- /dev/null +++ b/base/strings/string_piece_rust_unittest.cc
@@ -0,0 +1,30 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/strings/string_piece_rust.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace gurl_base { +namespace { + +TEST(BaseStringPieceRustTest, StrRoundTrip) { + std::string data = "hello"; + StringPiece data_piece(data); + rust::Str rust_str = StringPieceToRustStrUTF8(data_piece); + EXPECT_EQ(5ul, rust_str.length()); + StringPiece data_piece2 = RustStrToStringPiece(rust_str); + EXPECT_EQ(data_piece, data_piece2); +} + +TEST(BaseStringPieceRustTest, StrToSlice) { + std::string data = "hello"; + StringPiece data_piece(data); + rust::Slice<const uint8_t> rust_slice = StringPieceToRustSlice(data_piece); + EXPECT_EQ(5ul, rust_slice.length()); + EXPECT_EQ('e', rust_slice[1]); +} + +} // namespace +} // namespace base
diff --git a/base/strings/string_split.h b/base/strings/string_split.h index d7f56a6..b464f08 100644 --- a/base/strings/string_split.h +++ b/base/strings/string_split.h
@@ -45,16 +45,16 @@ // // std::vector<std::string> tokens = gurl_base::SplitString( // input, ",;", gurl_base::KEEP_WHITESPACE, gurl_base::SPLIT_WANT_ALL); -BASE_EXPORT std::vector<std::string> SplitString(StringPiece input, - StringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type) - WARN_UNUSED_RESULT; -BASE_EXPORT std::vector<std::u16string> SplitString( +[[nodiscard]] BASE_EXPORT std::vector<std::string> SplitString( + StringPiece input, + StringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type); +[[nodiscard]] BASE_EXPORT std::vector<std::u16string> SplitString( StringPiece16 input, StringPiece16 separators, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); // Like SplitString above except it returns a vector of StringPieces which // reference the original buffer without copying. Although you have to be @@ -70,16 +70,16 @@ // gurl_base::KEEP_WHITESPACE, // gurl_base::SPLIT_WANT_NONEMPTY)) { // ... -BASE_EXPORT std::vector<StringPiece> SplitStringPiece( +[[nodiscard]] BASE_EXPORT std::vector<StringPiece> SplitStringPiece( StringPiece input, StringPiece separators, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; -BASE_EXPORT std::vector<StringPiece16> SplitStringPiece( + SplitResult result_type); +[[nodiscard]] BASE_EXPORT std::vector<StringPiece16> SplitStringPiece( StringPiece16 input, StringPiece16 separators, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); using StringPairs = std::vector<std::pair<std::string, std::string>>; @@ -102,16 +102,16 @@ // Similar to SplitString, but use a substring delimiter instead of a list of // characters that are all possible delimiters. -BASE_EXPORT std::vector<std::u16string> SplitStringUsingSubstr( +[[nodiscard]] BASE_EXPORT std::vector<std::u16string> SplitStringUsingSubstr( StringPiece16 input, StringPiece16 delimiter, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; -BASE_EXPORT std::vector<std::string> SplitStringUsingSubstr( + SplitResult result_type); +[[nodiscard]] BASE_EXPORT std::vector<std::string> SplitStringUsingSubstr( StringPiece input, StringPiece delimiter, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); // Like SplitStringUsingSubstr above except it returns a vector of StringPieces // which reference the original buffer without copying. Although you have to be @@ -125,20 +125,20 @@ // gurl_base::KEEP_WHITESPACE, // gurl_base::SPLIT_WANT_NONEMPTY)) { // ... -BASE_EXPORT std::vector<StringPiece16> SplitStringPieceUsingSubstr( - StringPiece16 input, - StringPiece16 delimiter, - WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; -BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr( +[[nodiscard]] BASE_EXPORT std::vector<StringPiece16> +SplitStringPieceUsingSubstr(StringPiece16 input, + StringPiece16 delimiter, + WhitespaceHandling whitespace, + SplitResult result_type); +[[nodiscard]] BASE_EXPORT std::vector<StringPiece> SplitStringPieceUsingSubstr( StringPiece input, StringPiece delimiter, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); } // namespace base -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) #include "base/strings/string_split_win.h" #endif
diff --git a/base/strings/string_split_win.h b/base/strings/string_split_win.h index 850d2ca..74efb5d 100644 --- a/base/strings/string_split_win.h +++ b/base/strings/string_split_win.h
@@ -9,7 +9,6 @@ #include <vector> #include "polyfills/base/base_export.h" -#include "base/compiler_specific.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -17,29 +16,29 @@ // The following section contains overloads of the cross-platform APIs for // std::wstring and gurl_base::WStringPiece. -BASE_EXPORT std::vector<std::wstring> SplitString(WStringPiece input, - WStringPiece separators, - WhitespaceHandling whitespace, - SplitResult result_type) - WARN_UNUSED_RESULT; - -BASE_EXPORT std::vector<WStringPiece> SplitStringPiece( +[[nodiscard]] BASE_EXPORT std::vector<std::wstring> SplitString( WStringPiece input, WStringPiece separators, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); -BASE_EXPORT std::vector<std::wstring> SplitStringUsingSubstr( +[[nodiscard]] BASE_EXPORT std::vector<WStringPiece> SplitStringPiece( + WStringPiece input, + WStringPiece separators, + WhitespaceHandling whitespace, + SplitResult result_type); + +[[nodiscard]] BASE_EXPORT std::vector<std::wstring> SplitStringUsingSubstr( WStringPiece input, WStringPiece delimiter, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); -BASE_EXPORT std::vector<WStringPiece> SplitStringPieceUsingSubstr( +[[nodiscard]] BASE_EXPORT std::vector<WStringPiece> SplitStringPieceUsingSubstr( WStringPiece input, WStringPiece delimiter, WhitespaceHandling whitespace, - SplitResult result_type) WARN_UNUSED_RESULT; + SplitResult result_type); } // namespace base
diff --git a/base/strings/string_tokenizer_fuzzer.cc b/base/strings/string_tokenizer_fuzzer.cc index 3aaee7b..b3b046b 100644 --- a/base/strings/string_tokenizer_fuzzer.cc +++ b/base/strings/string_tokenizer_fuzzer.cc
@@ -6,12 +6,13 @@ #include <stdint.h> #include <string> +#include <tuple> #include "base/strings/string_tokenizer.h" void GetAllTokens(gurl_base::StringTokenizer& t) { while (t.GetNext()) { - (void)t.token(); + std::ignore = t.token(); } }
diff --git a/base/strings/string_util.h b/base/strings/string_util.h index 5995c2d..5d570e2 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h
@@ -505,9 +505,9 @@ } // namespace base -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) #include "base/strings/string_util_win.h" -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) #include "base/strings/string_util_posix.h" #else #error Define string operations appropriately for your platform
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc index 3f74e07..aed9b04 100644 --- a/base/strings/stringprintf.cc +++ b/base/strings/stringprintf.cc
@@ -33,7 +33,7 @@ return gurl_base::vsnprintf(buffer, buf_size, format, argptr); } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) inline int vsnprintfT(wchar_t* buffer, size_t buf_size, const wchar_t* format, @@ -77,7 +77,7 @@ int mem_length = gurl_base::size(stack_buf); while (true) { if (result < 0) { -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) // On Windows, vsnprintfT always returns the number of characters in a // fully-formatted string, so if we reach this point, something else is // wrong and no amount of buffer-doubling is going to fix it. @@ -128,7 +128,7 @@ return result; } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) std::wstring StringPrintf(const wchar_t* format, ...) { va_list ap; va_start(ap, format); @@ -163,7 +163,7 @@ return *dst; } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) const std::wstring& SStringPrintf(std::wstring* dst, const wchar_t* format, ...) { va_list ap; @@ -193,7 +193,7 @@ va_end(ap); } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { va_list ap; va_start(ap, format); @@ -213,7 +213,7 @@ StringAppendVT(dst, format, ap); } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { StringAppendVT(dst, format, ap); }
diff --git a/base/strings/stringprintf.h b/base/strings/stringprintf.h index 5768bcc..b0d473b 100644 --- a/base/strings/stringprintf.h +++ b/base/strings/stringprintf.h
@@ -16,28 +16,29 @@ namespace gurl_base { // Return a C++ string given printf-like input. -BASE_EXPORT std::string StringPrintf(const char* format, ...) - PRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; -#if defined(OS_WIN) +[[nodiscard]] BASE_EXPORT std::string StringPrintf(const char* format, ...) + PRINTF_FORMAT(1, 2); +#if BUILDFLAG(IS_WIN) // Note: Unfortunately compile time checking of the format string for UTF-16 // strings is not supported by any compiler, thus these functions should be used // carefully and sparingly. Also applies to SStringPrintf and StringAppendV // below. -BASE_EXPORT std::wstring StringPrintf(const wchar_t* format, ...) - WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; -BASE_EXPORT std::u16string StringPrintf(const char16_t* format, ...) - WPRINTF_FORMAT(1, 2) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring StringPrintf(const wchar_t* format, ...) + WPRINTF_FORMAT(1, 2); +[[nodiscard]] BASE_EXPORT std::u16string StringPrintf(const char16_t* format, + ...) WPRINTF_FORMAT(1, 2); #endif // Return a C++ string given vprintf-like input. -BASE_EXPORT std::string StringPrintV(const char* format, va_list ap) - PRINTF_FORMAT(1, 0) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string StringPrintV(const char* format, + va_list ap) + PRINTF_FORMAT(1, 0); // Store result into a supplied string and return it. BASE_EXPORT const std::string& SStringPrintf(std::string* dst, const char* format, ...) PRINTF_FORMAT(2, 3); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) BASE_EXPORT const std::wstring& SStringPrintf(std::wstring* dst, const wchar_t* format, ...) WPRINTF_FORMAT(2, 3); @@ -49,7 +50,7 @@ // Append result to a supplied string. BASE_EXPORT void StringAppendF(std::string* dst, const char* format, ...) PRINTF_FORMAT(2, 3); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) BASE_EXPORT void StringAppendF(std::wstring* dst, const wchar_t* format, ...) WPRINTF_FORMAT(2, 3); BASE_EXPORT void StringAppendF(std::u16string* dst, const char16_t* format, ...) @@ -60,7 +61,7 @@ // string. All other routines are just convenience wrappers around it. BASE_EXPORT void StringAppendV(std::string* dst, const char* format, va_list ap) PRINTF_FORMAT(2, 0); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) BASE_EXPORT void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) WPRINTF_FORMAT(2, 0);
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc index 9da8861..334d0ba 100644 --- a/base/strings/stringprintf_unittest.cc +++ b/base/strings/stringprintf_unittest.cc
@@ -35,7 +35,7 @@ TEST(StringPrintfTest, StringPrintfMisc) { EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w')); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) EXPECT_EQ(L"123hello w", StringPrintf(L"%3d%2ls %1lc", 123, L"hello", 'w')); EXPECT_EQ(u"123hello w", StringPrintf(u"%3d%2ls %1lc", 123, u"hello", 'w')); #endif @@ -46,7 +46,7 @@ StringAppendF(&value, "%s", ""); EXPECT_EQ("Hello", value); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) std::wstring valuew(L"Hello"); StringAppendF(&valuew, L"%ls", L""); EXPECT_EQ(L"Hello", valuew); @@ -62,7 +62,7 @@ StringAppendF(&value, " %s", "World"); EXPECT_EQ("Hello World", value); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) std::wstring valuew(L"Hello"); StringAppendF(&valuew, L" %ls", L"World"); EXPECT_EQ(L"Hello World", valuew); @@ -78,7 +78,7 @@ StringAppendF(&value, " %d", 123); EXPECT_EQ("Hello 123", value); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) std::wstring valuew(L"Hello"); StringAppendF(&valuew, L" %d", 123); EXPECT_EQ(L"Hello 123", valuew); @@ -108,7 +108,7 @@ SStringPrintf(&out, "%s", src); EXPECT_STREQ(src, out.c_str()); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) srcw[kSrcLen - i] = 0; std::wstring outw; SStringPrintf(&outw, L"%ls", srcw); @@ -139,9 +139,9 @@ const int kRefSize = 320000; char* ref = new char[kRefSize]; -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src); -#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src); #endif @@ -154,7 +154,7 @@ StringAppendVTestHelper(&out, "%d foo %s", 1, "bar"); EXPECT_EQ("1 foo bar", out); -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) std::wstring outw; StringAppendVTestHelper(&outw, L"%d foo %ls", 1, L"bar"); EXPECT_EQ(L"1 foo bar", outw); @@ -184,7 +184,7 @@ EXPECT_STREQ(src, out.c_str()); } -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) TEST(StringPrintfTest, Invalid) { wchar_t invalid[2]; invalid[0] = 0xffff;
diff --git a/base/strings/sys_string_conversions.h b/base/strings/sys_string_conversions.h index 51977fe..d80b178 100644 --- a/base/strings/sys_string_conversions.h +++ b/base/strings/sys_string_conversions.h
@@ -17,79 +17,76 @@ #include "base/strings/string_piece.h" #include "build/build_config.h" -#if defined(OS_APPLE) +#if BUILDFLAG(IS_APPLE) #include <CoreFoundation/CoreFoundation.h> #include "base/mac/scoped_cftyperef.h" #ifdef __OBJC__ @class NSString; -#else -class NSString; #endif -#endif // OS_APPLE +#endif // BUILDFLAG(IS_APPLE) namespace gurl_base { // Converts between wide and UTF-8 representations of a string. On error, the // result is system-dependent. -BASE_EXPORT std::string SysWideToUTF8(const std::wstring& wide) - WARN_UNUSED_RESULT; -BASE_EXPORT std::wstring SysUTF8ToWide(StringPiece utf8) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string SysWideToUTF8(const std::wstring& wide); +[[nodiscard]] BASE_EXPORT std::wstring SysUTF8ToWide(StringPiece utf8); // Converts between wide and the system multi-byte representations of a string. // DANGER: This will lose information and can change (on Windows, this can // change between reboots). -BASE_EXPORT std::string SysWideToNativeMB(const std::wstring& wide) - WARN_UNUSED_RESULT; -BASE_EXPORT std::wstring SysNativeMBToWide(StringPiece native_mb) - WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string SysWideToNativeMB( + const std::wstring& wide); +[[nodiscard]] BASE_EXPORT std::wstring SysNativeMBToWide(StringPiece native_mb); // Windows-specific ------------------------------------------------------------ -#if defined(OS_WIN) +#if BUILDFLAG(IS_WIN) // Converts between 8-bit and wide strings, using the given code page. The // code page identifier is one accepted by the Windows function // MultiByteToWideChar(). -BASE_EXPORT std::wstring SysMultiByteToWide(StringPiece mb, uint32_t code_page) - WARN_UNUSED_RESULT; -BASE_EXPORT std::string SysWideToMultiByte(const std::wstring& wide, - uint32_t code_page) - WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring SysMultiByteToWide(StringPiece mb, + uint32_t code_page); +[[nodiscard]] BASE_EXPORT std::string SysWideToMultiByte( + const std::wstring& wide, + uint32_t code_page); -#endif // defined(OS_WIN) +#endif // BUILDFLAG(IS_WIN) // Mac-specific ---------------------------------------------------------------- -#if defined(OS_APPLE) +#if BUILDFLAG(IS_APPLE) -// Converts between STL strings and CFStringRefs/NSStrings. +// Converts between strings and CFStringRefs/NSStrings. -// Creates a string, and returns it with a refcount of 1. You are responsible -// for releasing it. Returns NULL on failure. -BASE_EXPORT ScopedCFTypeRef<CFStringRef> SysUTF8ToCFStringRef(StringPiece utf8) - WARN_UNUSED_RESULT; -BASE_EXPORT ScopedCFTypeRef<CFStringRef> SysUTF16ToCFStringRef( - StringPiece16 utf16) WARN_UNUSED_RESULT; +// Converts a string to a CFStringRef. Returns null on failure. +[[nodiscard]] BASE_EXPORT ScopedCFTypeRef<CFStringRef> SysUTF8ToCFStringRef( + StringPiece utf8); +[[nodiscard]] BASE_EXPORT ScopedCFTypeRef<CFStringRef> SysUTF16ToCFStringRef( + StringPiece16 utf16); -// Same, but returns an autoreleased NSString. -BASE_EXPORT NSString* SysUTF8ToNSString(StringPiece utf8) WARN_UNUSED_RESULT; -BASE_EXPORT NSString* SysUTF16ToNSString(StringPiece16 utf16) - WARN_UNUSED_RESULT; +// Converts a CFStringRef to a string. Returns an empty string on failure. It is +// not valid to call these with a null `ref`. +[[nodiscard]] BASE_EXPORT std::string SysCFStringRefToUTF8(CFStringRef ref); +[[nodiscard]] BASE_EXPORT std::u16string SysCFStringRefToUTF16(CFStringRef ref); -// Converts a CFStringRef to an STL string. Returns an empty string on failure. -BASE_EXPORT std::string SysCFStringRefToUTF8(CFStringRef ref) - WARN_UNUSED_RESULT; -BASE_EXPORT std::u16string SysCFStringRefToUTF16(CFStringRef ref) - WARN_UNUSED_RESULT; +#ifdef __OBJC__ -// Same, but accepts NSString input. Converts nil NSString* to the appropriate -// string type of length 0. -BASE_EXPORT std::string SysNSStringToUTF8(NSString* ref) WARN_UNUSED_RESULT; -BASE_EXPORT std::u16string SysNSStringToUTF16(NSString* ref) WARN_UNUSED_RESULT; +// Converts a string to an autoreleased NSString. Returns nil on failure. +[[nodiscard]] BASE_EXPORT NSString* SysUTF8ToNSString(StringPiece utf8); +[[nodiscard]] BASE_EXPORT NSString* SysUTF16ToNSString(StringPiece16 utf16); -#endif // defined(OS_APPLE) +// Converts an NSString to a string. Returns an empty string on failure or if +// `ref` is nil. +[[nodiscard]] BASE_EXPORT std::string SysNSStringToUTF8(NSString* ref); +[[nodiscard]] BASE_EXPORT std::u16string SysNSStringToUTF16(NSString* ref); + +#endif // __OBJC__ + +#endif // BUILDFLAG(IS_APPLE) } // namespace base
diff --git a/base/strings/sys_string_conversions_posix.cc b/base/strings/sys_string_conversions_posix.cc index f9f7312..02535ed 100644 --- a/base/strings/sys_string_conversions_posix.cc +++ b/base/strings/sys_string_conversions_posix.cc
@@ -27,7 +27,7 @@ return out; } -#if defined(SYSTEM_NATIVE_UTF8) || defined(OS_ANDROID) +#if defined(SYSTEM_NATIVE_UTF8) || BUILDFLAG(IS_ANDROID) // TODO(port): Consider reverting the OS_ANDROID when we have wcrtomb() // support and a better understanding of what calls these routines. @@ -116,7 +116,7 @@ case 0: // We hit an embedded null byte, keep going. i += 1; - FALLTHROUGH; + [[fallthrough]]; default: i += res; ++num_out_chars; @@ -154,6 +154,6 @@ return out; } -#endif // defined(SYSTEM_NATIVE_UTF8) || defined(OS_ANDROID) +#endif // defined(SYSTEM_NATIVE_UTF8) || BUILDFLAG(IS_ANDROID) } // namespace base
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc index 95995c6..01bceb0 100644 --- a/base/strings/sys_string_conversions_unittest.cc +++ b/base/strings/sys_string_conversions_unittest.cc
@@ -75,7 +75,7 @@ } // Tests depend on setting a specific Linux locale. -#if defined(OS_LINUX) || defined(OS_CHROMEOS) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) TEST(SysStrings, SysWideToNativeMB) { #if !defined(SYSTEM_NATIVE_UTF8) ScopedLocale locale("en_US.UTF-8"); @@ -190,6 +190,6 @@ EXPECT_EQ(wide, trip); } } -#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) } // namespace base
diff --git a/base/strings/utf_offset_string_conversions.h b/base/strings/utf_offset_string_conversions.h index aa4e59e..3b2904d 100644 --- a/base/strings/utf_offset_string_conversions.h +++ b/base/strings/utf_offset_string_conversions.h
@@ -96,9 +96,9 @@ size_t src_len, std::u16string* output, gurl_base::OffsetAdjuster::Adjustments* adjustments); -BASE_EXPORT std::u16string UTF8ToUTF16WithAdjustments( +[[nodiscard]] BASE_EXPORT std::u16string UTF8ToUTF16WithAdjustments( const gurl_base::StringPiece& utf8, - gurl_base::OffsetAdjuster::Adjustments* adjustments) WARN_UNUSED_RESULT; + gurl_base::OffsetAdjuster::Adjustments* adjustments); // As above, but instead internally examines the adjustments and applies them // to |offsets_for_adjustment|. Input offsets greater than the length of the // input string will be set to std::u16string::npos. See comments by
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc index da68dd3..9a4b4ca 100644 --- a/base/strings/utf_string_conversion_utils.cc +++ b/base/strings/utf_string_conversion_utils.cc
@@ -122,7 +122,7 @@ } // Instantiate versions we know callers will need. -#if !defined(OS_WIN) +#if !BUILDFLAG(IS_WIN) // wchar_t and char16_t are the same thing on Windows. template void PrepareForUTF8Output(const wchar_t*, size_t, std::string*); #endif @@ -146,7 +146,7 @@ } // Instantiate versions we know callers will need. -#if !defined(OS_WIN) +#if !BUILDFLAG(IS_WIN) // std::wstring and std::u16string are the same thing on Windows. template void PrepareForUTF16Or32Output(const char*, size_t, std::wstring*); #endif
diff --git a/base/strings/utf_string_conversions.h b/base/strings/utf_string_conversions.h index ffb56e4..77dc194 100644 --- a/base/strings/utf_string_conversions.h +++ b/base/strings/utf_string_conversions.h
@@ -23,45 +23,45 @@ // possible. BASE_EXPORT bool WideToUTF8(const wchar_t* src, size_t src_len, std::string* output); -BASE_EXPORT std::string WideToUTF8(WStringPiece wide) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string WideToUTF8(WStringPiece wide); BASE_EXPORT bool UTF8ToWide(const char* src, size_t src_len, std::wstring* output); -BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring UTF8ToWide(StringPiece utf8); BASE_EXPORT bool WideToUTF16(const wchar_t* src, size_t src_len, std::u16string* output); -BASE_EXPORT std::u16string WideToUTF16(WStringPiece wide) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::u16string WideToUTF16(WStringPiece wide); BASE_EXPORT bool UTF16ToWide(const char16_t* src, size_t src_len, std::wstring* output); -BASE_EXPORT std::wstring UTF16ToWide(StringPiece16 utf16) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring UTF16ToWide(StringPiece16 utf16); BASE_EXPORT bool UTF8ToUTF16(const char* src, size_t src_len, std::u16string* output); -BASE_EXPORT std::u16string UTF8ToUTF16(StringPiece utf8) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::u16string UTF8ToUTF16(StringPiece utf8); BASE_EXPORT bool UTF16ToUTF8(const char16_t* src, size_t src_len, std::string* output); -BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string UTF16ToUTF8(StringPiece16 utf16); // This converts an ASCII string, typically a hardcoded constant, to a UTF16 // string. -BASE_EXPORT std::u16string ASCIIToUTF16(StringPiece ascii) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::u16string ASCIIToUTF16(StringPiece ascii); // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII // beforehand. -BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string UTF16ToASCII(StringPiece16 utf16); #if defined(WCHAR_T_IS_UTF16) // This converts an ASCII string, typically a hardcoded constant, to a wide // string. -BASE_EXPORT std::wstring ASCIIToWide(StringPiece ascii) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::wstring ASCIIToWide(StringPiece ascii); // Converts to 7-bit ASCII by truncating. The result must be known to be ASCII // beforehand. -BASE_EXPORT std::string WideToASCII(WStringPiece wide) WARN_UNUSED_RESULT; +[[nodiscard]] BASE_EXPORT std::string WideToASCII(WStringPiece wide); #endif // defined(WCHAR_T_IS_UTF16) // The conversion functions in this file should not be used to convert string
diff --git a/base/strings/utf_string_conversions_fuzzer.cc b/base/strings/utf_string_conversions_fuzzer.cc index 932012a..7bae707 100644 --- a/base/strings/utf_string_conversions_fuzzer.cc +++ b/base/strings/utf_string_conversions_fuzzer.cc
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/macros.h" +#include <tuple> + #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -15,10 +16,10 @@ gurl_base::StringPiece string_piece_input(reinterpret_cast<const char*>(data), size); - ignore_result(gurl_base::UTF8ToWide(string_piece_input)); + std::ignore = gurl_base::UTF8ToWide(string_piece_input); gurl_base::UTF8ToWide(reinterpret_cast<const char*>(data), size, &output_std_wstring); - ignore_result(gurl_base::UTF8ToUTF16(string_piece_input)); + std::ignore = gurl_base::UTF8ToUTF16(string_piece_input); gurl_base::UTF8ToUTF16(reinterpret_cast<const char*>(data), size, &output_string16); @@ -26,10 +27,10 @@ if (size % 2 == 0) { gurl_base::StringPiece16 string_piece_input16( reinterpret_cast<const char16_t*>(data), size / 2); - ignore_result(gurl_base::UTF16ToWide(output_string16)); + std::ignore = gurl_base::UTF16ToWide(output_string16); gurl_base::UTF16ToWide(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_wstring); - ignore_result(gurl_base::UTF16ToUTF8(string_piece_input16)); + std::ignore = gurl_base::UTF16ToUTF8(string_piece_input16); gurl_base::UTF16ToUTF8(reinterpret_cast<const char16_t*>(data), size / 2, &output_std_string); } @@ -37,10 +38,10 @@ // Test for wchar_t. size_t wchar_t_size = sizeof(wchar_t); if (size % wchar_t_size == 0) { - ignore_result(gurl_base::WideToUTF8(output_std_wstring)); + std::ignore = gurl_base::WideToUTF8(output_std_wstring); gurl_base::WideToUTF8(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_std_string); - ignore_result(gurl_base::WideToUTF16(output_std_wstring)); + std::ignore = gurl_base::WideToUTF16(output_std_wstring); gurl_base::WideToUTF16(reinterpret_cast<const wchar_t*>(data), size / wchar_t_size, &output_string16); } @@ -50,7 +51,7 @@ if (gurl_base::IsStringASCII(string_piece_input)) { output_string16 = gurl_base::ASCIIToUTF16(string_piece_input); gurl_base::StringPiece16 string_piece_input16(output_string16); - ignore_result(gurl_base::UTF16ToASCII(string_piece_input16)); + std::ignore = gurl_base::UTF16ToASCII(string_piece_input16); } return 0;
diff --git a/base/template_util.h b/base/template_util.h index d0803f8..3d954fd 100644 --- a/base/template_util.h +++ b/base/template_util.h
@@ -12,7 +12,6 @@ #include <utility> #include "base/compiler_specific.h" -#include "build/build_config.h" #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 7 #include <vector> @@ -247,7 +246,7 @@ // [1] https://en.cppreference.com/w/cpp/types/result_of // [2] https://wg21.link/meta.trans.other#lib:invoke_result template <typename Functor, typename... Args> -using invoke_result = std::result_of<Functor && (Args && ...)>; +using invoke_result = std::invoke_result<Functor, Args...>; // Implementation of C++17's std::invoke_result_t. //
diff --git a/build/BUILD b/build/BUILD index 79fa1dd..5b560c9 100644 --- a/build/BUILD +++ b/build/BUILD
@@ -10,3 +10,10 @@ copts = build_config.default_copts, visibility = ["//visibility:public"], ) + +cc_library( + name = "buildflag", + hdrs = ["buildflag.h"], + copts = build_config.default_copts, + visibility = ["//visibility:public"], +)
diff --git a/build/build_config.h b/build/build_config.h index 63cec87..0102a93 100644 --- a/build/build_config.h +++ b/build/build_config.h
@@ -2,33 +2,46 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file adds defines about the platform we're currently building on. +// This file doesn't belong to any GN target by design for faster build and +// less developer overhead. + +// This file adds build flags about the OS we're currently building on. They are +// defined directly in this file instead of via a `buildflag_header` target in a +// GN file for faster build. They are defined using the corresponding OS defines +// (e.g. OS_WIN) which are also defined in this file (except for OS_CHROMEOS, +// which is set by the build system). These defines are deprecated and should +// NOT be used directly. For example: +// Please Use: #if BUILDFLAG(IS_WIN) +// Deprecated: #if defined(OS_WIN) // // Operating System: -// OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS / -// OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD / -// OS_QNX / OS_SOLARIS / OS_WIN +// IS_AIX / IS_ANDROID / IS_ASMJS / IS_CHROMEOS / IS_FREEBSD / IS_FUCHSIA / +// IS_IOS / IS_LINUX / IS_MAC / IS_NACL / IS_NETBSD / IS_OPENBSD / IS_QNX / +// IS_SOLARIS / IS_WIN // Operating System family: -// OS_APPLE: IOS or MAC -// OS_BSD: FREEBSD or NETBSD or OPENBSD -// OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX +// IS_APPLE: IOS or MAC +// IS_BSD: FREEBSD or NETBSD or OPENBSD +// IS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX // or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS -// -// /!\ Note: OS_CHROMEOS is set by the build system, not this file + +// This file also adds defines specific to the platform, architecture etc. // // Compiler: // COMPILER_MSVC / COMPILER_GCC // // Processor: -// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 / -// ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 / -// ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64 +// ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_LOONG32 / ARCH_CPU_LOONG64 / +// ARCH_CPU_MIPS / ARCH_CPU_MIPS64 / ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / +// ARCH_CPU_PPC64 / ARCH_CPU_S390 / ARCH_CPU_S390X / ARCH_CPU_X86 / +// ARCH_CPU_X86_64 / ARCH_CPU_RISCV64 // Processor family: // ARCH_CPU_ARM_FAMILY: ARMEL or ARM64 +// ARCH_CPU_LOONG_FAMILY: LOONG32 or LOONG64 // ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS // ARCH_CPU_PPC64_FAMILY: PPC64 // ARCH_CPU_S390_FAMILY: S390 or S390X // ARCH_CPU_X86_FAMILY: X86 or X86_64 +// ARCH_CPU_RISCV_FAMILY: Riscv64 // Processor features: // ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS // ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN @@ -36,18 +49,12 @@ #ifndef BUILD_BUILD_CONFIG_H_ #define BUILD_BUILD_CONFIG_H_ +#include "build/buildflag.h" + // A set of macros to use for platform detection. #if defined(__native_client__) // __native_client__ must be first, so that other OS_ defines are not set. #define OS_NACL 1 -// OS_NACL comes in two sandboxing technology flavors, SFI or Non-SFI. -// PNaCl toolchain defines __native_client_nonsfi__ macro in Non-SFI build -// mode, while it does not in SFI build mode. -#if defined(__native_client_nonsfi__) -#define OS_NACL_NONSFI -#else -#define OS_NACL_SFI -#endif #elif defined(ANDROID) #define OS_ANDROID 1 #elif defined(__APPLE__) @@ -67,7 +74,7 @@ #define OS_LINUX 1 #endif // !defined(OS_CHROMEOS) // Include a system header to pull in features.h for glibc/uclibc macros. -#include <unistd.h> +#include <assert.h> #if defined(__GLIBC__) && !defined(__UCLIBC__) // We really are using glibc, not uClibc pretending to be glibc. #define LIBC_GLIBC 1 @@ -118,6 +125,115 @@ #define OS_POSIX 1 #endif +// OS build flags +#if defined(OS_AIX) +#define BUILDFLAG_INTERNAL_IS_AIX() (1) +#else +#define BUILDFLAG_INTERNAL_IS_AIX() (0) +#endif + +#if defined(OS_ANDROID) +#define BUILDFLAG_INTERNAL_IS_ANDROID() (1) +#else +#define BUILDFLAG_INTERNAL_IS_ANDROID() (0) +#endif + +#if defined(OS_APPLE) +#define BUILDFLAG_INTERNAL_IS_APPLE() (1) +#else +#define BUILDFLAG_INTERNAL_IS_APPLE() (0) +#endif + +#if defined(OS_ASMJS) +#define BUILDFLAG_INTERNAL_IS_ASMJS() (1) +#else +#define BUILDFLAG_INTERNAL_IS_ASMJS() (0) +#endif + +#if defined(OS_BSD) +#define BUILDFLAG_INTERNAL_IS_BSD() (1) +#else +#define BUILDFLAG_INTERNAL_IS_BSD() (0) +#endif + +#if defined(OS_CHROMEOS) +#define BUILDFLAG_INTERNAL_IS_CHROMEOS() (1) +#else +#define BUILDFLAG_INTERNAL_IS_CHROMEOS() (0) +#endif + +#if defined(OS_FREEBSD) +#define BUILDFLAG_INTERNAL_IS_FREEBSD() (1) +#else +#define BUILDFLAG_INTERNAL_IS_FREEBSD() (0) +#endif + +#if defined(OS_FUCHSIA) +#define BUILDFLAG_INTERNAL_IS_FUCHSIA() (1) +#else +#define BUILDFLAG_INTERNAL_IS_FUCHSIA() (0) +#endif + +#if defined(OS_IOS) +#define BUILDFLAG_INTERNAL_IS_IOS() (1) +#else +#define BUILDFLAG_INTERNAL_IS_IOS() (0) +#endif + +#if defined(OS_LINUX) +#define BUILDFLAG_INTERNAL_IS_LINUX() (1) +#else +#define BUILDFLAG_INTERNAL_IS_LINUX() (0) +#endif + +#if defined(OS_MAC) +#define BUILDFLAG_INTERNAL_IS_MAC() (1) +#else +#define BUILDFLAG_INTERNAL_IS_MAC() (0) +#endif + +#if defined(OS_NACL) +#define BUILDFLAG_INTERNAL_IS_NACL() (1) +#else +#define BUILDFLAG_INTERNAL_IS_NACL() (0) +#endif + +#if defined(OS_NETBSD) +#define BUILDFLAG_INTERNAL_IS_NETBSD() (1) +#else +#define BUILDFLAG_INTERNAL_IS_NETBSD() (0) +#endif + +#if defined(OS_OPENBSD) +#define BUILDFLAG_INTERNAL_IS_OPENBSD() (1) +#else +#define BUILDFLAG_INTERNAL_IS_OPENBSD() (0) +#endif + +#if defined(OS_POSIX) +#define BUILDFLAG_INTERNAL_IS_POSIX() (1) +#else +#define BUILDFLAG_INTERNAL_IS_POSIX() (0) +#endif + +#if defined(OS_QNX) +#define BUILDFLAG_INTERNAL_IS_QNX() (1) +#else +#define BUILDFLAG_INTERNAL_IS_QNX() (0) +#endif + +#if defined(OS_SOLARIS) +#define BUILDFLAG_INTERNAL_IS_SOLARIS() (1) +#else +#define BUILDFLAG_INTERNAL_IS_SOLARIS() (0) +#endif + +#if defined(OS_WIN) +#define BUILDFLAG_INTERNAL_IS_WIN() (1) +#else +#define BUILDFLAG_INTERNAL_IS_WIN() (0) +#endif + // Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on // Windows. #if defined(__GNUC__) @@ -199,6 +315,21 @@ #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_BIG_ENDIAN 1 #endif +#elif defined(__loongarch32) +#define ARCH_CPU_LOONG_FAMILY 1 +#define ARCH_CPU_LOONG32 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__loongarch64) +#define ARCH_CPU_LOONG_FAMILY 1 +#define ARCH_CPU_LOONG64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__riscv) && (__riscv_xlen == 64) +#define ARCH_CPU_RISCV_FAMILY 1 +#define ARCH_CPU_RISCV64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 #else #error Please add support for your architecture in build/build_config.h #endif
diff --git a/build/buildflag.h b/build/buildflag.h new file mode 100644 index 0000000..5776a75 --- /dev/null +++ b/build/buildflag.h
@@ -0,0 +1,47 @@ +// Copyright 2015 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 BUILD_BUILDFLAG_H_ +#define BUILD_BUILDFLAG_H_ + +// These macros un-mangle the names of the build flags in a way that looks +// natural, and gives errors if the flag is not defined. Normally in the +// preprocessor it's easy to make mistakes that interpret "you haven't done +// the setup to know what the flag is" as "flag is off". Normally you would +// include the generated header rather than include this file directly. +// +// This is for use with generated headers. See build/buildflag_header.gni. + +// This dance of two macros does a concatenation of two preprocessor args using +// ## doubly indirectly because using ## directly prevents macros in that +// parameter from being expanded. +#define BUILDFLAG_CAT_INDIRECT(a, b) a ## b +#define BUILDFLAG_CAT(a, b) BUILDFLAG_CAT_INDIRECT(a, b) + +// Accessor for build flags. +// +// To test for a value, if the build file specifies: +// +// ENABLE_FOO=true +// +// Then you would check at build-time in source code with: +// +// #include "foo_flags.h" // The header the build file specified. +// +// #if BUILDFLAG(ENABLE_FOO) +// ... +// #endif +// +// There will no #define called ENABLE_FOO so if you accidentally test for +// whether that is defined, it will always be negative. You can also use +// the value in expressions: +// +// const char kSpamServerName[] = BUILDFLAG(SPAM_SERVER_NAME); +// +// Because the flag is accessed as a preprocessor macro with (), an error +// will be thrown if the proper header defining the internal flag value has +// not been included. +#define BUILDFLAG(flag) (BUILDFLAG_CAT(BUILDFLAG_INTERNAL_, flag)()) + +#endif // BUILD_BUILDFLAG_H_
diff --git a/build_config/build_config.bzl b/build_config/build_config.bzl index 117bc96..3deb9d1 100644 --- a/build_config/build_config.bzl +++ b/build_config/build_config.bzl
@@ -11,8 +11,8 @@ }) _strings_hdrs = select({ - "//build_config:windows_x86_64": ["string_util_win.h"], - "//conditions:default": ["string_util_posix.h"], + "//build_config:windows_x86_64": ["strings/string_util_win.h"], + "//conditions:default": ["strings/string_util_posix.h"], }) _url_linkopts = select({
diff --git a/copy.bara.sky b/copy.bara.sky index ffe4f61..6bf0772 100644 --- a/copy.bara.sky +++ b/copy.bara.sky
@@ -20,10 +20,12 @@ "base/containers/util.h", "base/cxx17_backports.h", "base/cxx20_to_address.h", + "base/debug/crash_logging.cc", + "base/debug/crash_logging.h", "base/debug/leak_annotations.h", "base/functional/*.h", "base/i18n/uchar.h", - "base/macros.h", + "base/memory/raw_ptr.h", "base/no_destructor.h", "base/ranges/*.h", "base/stl_util.h", @@ -32,6 +34,7 @@ "base/template_util.h", "base/third_party/icu/**", "build/build_config.h", + "build/buildflag.h", "url/*.cc", "url/*.h", "url/third_party/mozilla/**", @@ -57,10 +60,13 @@ # Those headers are pulled from //polyfill instead of copied from Chromium. # Should be in sync with //polyfill/BUILD. polyfilled_headers = [ + "base/allocator/buildflags.h", "base/base_export.h", "base/check.h", "base/check_op.h", "base/component_export.h", + "base/cpu_reduction_experiment.h", + "base/dcheck_is_on.h", "base/debug/alias.h", "base/export_template.h", "base/logging.h",
diff --git a/polyfills/BUILD b/polyfills/BUILD index 9bf74f4..6a58eec 100644 --- a/polyfills/BUILD +++ b/polyfills/BUILD
@@ -6,10 +6,13 @@ cc_library( name = "polyfills", hdrs = [ + "base/allocator/buildflags.h", "base/base_export.h", "base/check.h", "base/check_op.h", "base/component_export.h", + "base/cpu_reduction_experiment.h", + "base/dcheck_is_on.h", "base/debug/alias.h", "base/export_template.h", "base/logging.h",
diff --git a/polyfills/base/allocator/buildflags.h b/polyfills/base/allocator/buildflags.h new file mode 100644 index 0000000..54e240c --- /dev/null +++ b/polyfills/base/allocator/buildflags.h
@@ -0,0 +1,18 @@ +#ifndef POLYFILLS_BASE_ALLOCATOR_BUILDFLAGS_H_ +#define POLYFILLS_BASE_ALLOCATOR_BUILDFLAGS_H_ + +#include "build/buildflag.h" + +#define BUILDFLAG_INTERNAL_USE_ALLOCATOR_SHIM() (1) +#define BUILDFLAG_INTERNAL_USE_PARTITION_ALLOC() (1) +#define BUILDFLAG_INTERNAL_USE_PARTITION_ALLOC_AS_MALLOC() (0) +#define BUILDFLAG_INTERNAL_USE_BACKUP_REF_PTR() (0) +#define BUILDFLAG_INTERNAL_USE_ASAN_BACKUP_REF_PTR() (0) +#define BUILDFLAG_INTERNAL_ENABLE_BACKUP_REF_PTR_SLOW_CHECKS() (0) +#define BUILDFLAG_INTERNAL_ENABLE_DANGLING_RAW_PTR_CHECKS() (0) +#define BUILDFLAG_INTERNAL_PUT_REF_COUNT_IN_PREVIOUS_SLOT() (0) +#define BUILDFLAG_INTERNAL_NEVER_REMOVE_FROM_BRP_POOL_BLOCKLIST() (0) +#define BUILDFLAG_INTERNAL_USE_FAKE_BINARY_EXPERIMENT() (0) +#define BUILDFLAG_INTERNAL_RECORD_ALLOC_INFO() (0) + +#endif // POLYFILLS_BASE_ALLOCATOR_BUILDFLAGS_H_
diff --git a/polyfills/base/check.h b/polyfills/base/check.h index 15de08b..5c4168d 100644 --- a/polyfills/base/check.h +++ b/polyfills/base/check.h
@@ -5,6 +5,7 @@ #ifndef POLYFILLS_BASE_CHECK_H_ #define POLYFILLS_BASE_CHECK_H_ +#include "polyfills/base/base_export.h" #include "polyfills/base/logging.h" #endif /* POLYFILLS_BASE_CHECK_H_ */
diff --git a/polyfills/base/cpu_reduction_experiment.h b/polyfills/base/cpu_reduction_experiment.h new file mode 100644 index 0000000..db2ea65 --- /dev/null +++ b/polyfills/base/cpu_reduction_experiment.h
@@ -0,0 +1,20 @@ +// Copyright 2022 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 POLYFILLS_BASE_CPU_REDUCTION_EXPERIMENT_H_ +#define POLYFILLS_BASE_CPU_REDUCTION_EXPERIMENT_H_ + +namespace base { + +inline bool IsRunningCpuReductionExperiment() { return false; } + +class CpuReductionExperimentFilter { + public: + bool ShouldLogHistograms() { return false; } +}; + +} // namespace base + + +#endif /* POLYFILLS_BASE_CPU_REDUCTION_EXPERIMENT_H_ */
diff --git a/polyfills/base/dcheck_is_on.h b/polyfills/base/dcheck_is_on.h new file mode 100644 index 0000000..814f0d2 --- /dev/null +++ b/polyfills/base/dcheck_is_on.h
@@ -0,0 +1,11 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef POLYFILLS_BASE_DCHECK_IS_ON_H_ +#define POLYFILLS_BASE_DCHECK_IS_ON_H_ + +#define DCHECK_IS_ON() false +#define EXPENSIVE_DCHECKS_ARE_ON() false + +#endif // POLYFILLS_BASE_DCHECK_IS_ON_H_
diff --git a/url/BUILD b/url/BUILD index f2ec8da..24fd97e 100644 --- a/url/BUILD +++ b/url/BUILD
@@ -48,7 +48,6 @@ visibility = ["//visibility:public"], deps = [ "//base", - "//base/strings", "//polyfills", ] + build_config.icuuc_deps, )
diff --git a/url/gurl.cc b/url/gurl.cc index 474919a..3dd0228 100644 --- a/url/gurl.cc +++ b/url/gurl.cc
@@ -349,7 +349,7 @@ GURL_DCHECK(gurl_base::IsStringASCII(lower_ascii_scheme)); GURL_DCHECK(gurl_base::ToLowerASCII(lower_ascii_scheme) == lower_ascii_scheme); - if (parsed_.scheme.len <= 0) + if (!has_scheme()) return lower_ascii_scheme.empty(); return scheme_piece() == lower_ascii_scheme; } @@ -363,7 +363,7 @@ } bool GURL::SchemeIsCryptographic() const { - if (parsed_.scheme.len <= 0) + if (!has_scheme()) return false; return SchemeIsCryptographic(scheme_piece()); } @@ -376,6 +376,13 @@ lower_ascii_scheme == url::kWssScheme; } +bool GURL::SchemeIsLocal() const { + // The `filesystem:` scheme is not in the Fetch spec, but Chromium still + // supports it in large part. It should be treated as a local scheme too. + return SchemeIs(url::kAboutScheme) || SchemeIs(url::kBlobScheme) || + SchemeIs(url::kDataScheme) || SchemeIs(url::kFileSystemScheme); +} + int GURL::IntPort() const { if (parsed_.port.is_nonempty()) return url::ParsePort(spec_.data(), parsed_.port); @@ -546,3 +553,15 @@ bool operator!=(const gurl_base::StringPiece& spec, const GURL& x) { return !(x == spec); } + +namespace url::debug { + +ScopedUrlCrashKey::ScopedUrlCrashKey(gurl_base::debug::CrashKeyString* crash_key, + const GURL& url) + : scoped_string_value_( + crash_key, + url.is_empty() ? "<empty url>" : url.possibly_invalid_spec()) {} + +ScopedUrlCrashKey::~ScopedUrlCrashKey() = default; + +} // namespace url::debug
diff --git a/url/gurl.h b/url/gurl.h index 64a2ee3..ee009de 100644 --- a/url/gurl.h +++ b/url/gurl.h
@@ -13,6 +13,7 @@ #include "polyfills/base/component_export.h" #include "polyfills/base/debug/alias.h" +#include "base/debug/crash_logging.h" #include "base/strings/string_piece.h" #include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" #include "url/third_party/mozilla/url_parse.h" @@ -265,6 +266,10 @@ return SchemeIs(url::kBlobScheme); } + // Returns true if the scheme is a local scheme, as defined in Fetch: + // https://fetch.spec.whatwg.org/#local-scheme + bool SchemeIsLocal() const; + // For most URLs, the "content" is everything after the scheme (skipping the // scheme delimiting colon) and before the fragment (skipping the fragment // delimiting octothorpe). For javascript URLs the "content" also includes the @@ -516,4 +521,20 @@ #define DEBUG_ALIAS_FOR_GURL(var_name, url) \ DEBUG_ALIAS_FOR_CSTR(var_name, (url).possibly_invalid_spec().c_str(), 128) +namespace url::debug { + +class COMPONENT_EXPORT(URL) ScopedUrlCrashKey { + public: + ScopedUrlCrashKey(gurl_base::debug::CrashKeyString* crash_key, const GURL& value); + ~ScopedUrlCrashKey(); + + ScopedUrlCrashKey(const ScopedUrlCrashKey&) = delete; + ScopedUrlCrashKey& operator=(const ScopedUrlCrashKey&) = delete; + + private: + gurl_base::debug::ScopedCrashKeyString scoped_string_value_; +}; + +} // namespace url::debug + #endif // URL_GURL_H_
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc index 68817af..e793542 100644 --- a/url/gurl_unittest.cc +++ b/url/gurl_unittest.cc
@@ -18,19 +18,6 @@ namespace { -template<typename CHAR> -void SetupReplacement( - void (Replacements<CHAR>::*func)(const CHAR*, const Component&), - Replacements<CHAR>* replacements, - const CHAR* str) { - if (str) { - Component comp; - if (str[0]) - comp.len = static_cast<int>(strlen(str)); - (replacements->*func)(str, comp); - } -} - // Returns the canonicalized string for the given URL string for the // GURLTest.Types test. std::string TypesTestCase(const char* src) { @@ -496,60 +483,102 @@ // The most important thing to do here is to check that the proper // canonicalizer gets called based on the scheme of the input. struct ReplaceCase { + using ApplyReplacementsFunc = GURL(const GURL&); + const char* base; - const char* scheme; - const char* username; - const char* password; - const char* host; - const char* port; - const char* path; - const char* query; - const char* ref; + ApplyReplacementsFunc* apply_replacements; const char* expected; } replace_cases[] = { - {"http://www.google.com/foo/bar.html?foo#bar", nullptr, nullptr, nullptr, - nullptr, nullptr, "/", "", "", "http://www.google.com/"}, - {"http://www.google.com/foo/bar.html?foo#bar", "javascript", "", "", "", - "", "window.open('foo');", "", "", "javascript:window.open('foo');"}, - {"file:///C:/foo/bar.txt", "http", nullptr, nullptr, "www.google.com", - "99", "/foo", "search", "ref", - "http://www.google.com:99/foo?search#ref"}, + {.base = "http://www.google.com/foo/bar.html?foo#bar", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetPathStr("/"); + replacements.ClearQuery(); + replacements.ClearRef(); + return url.ReplaceComponents(replacements); + }, + .expected = "http://www.google.com/"}, + {.base = "http://www.google.com/foo/bar.html?foo#bar", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetSchemeStr("javascript"); + replacements.ClearUsername(); + replacements.ClearPassword(); + replacements.ClearHost(); + replacements.ClearPort(); + replacements.SetPathStr("window.open('foo');"); + replacements.ClearQuery(); + replacements.ClearRef(); + return url.ReplaceComponents(replacements); + }, + .expected = "javascript:window.open('foo');"}, + {.base = "file:///C:/foo/bar.txt", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetSchemeStr("http"); + replacements.SetHostStr("www.google.com"); + replacements.SetPortStr("99"); + replacements.SetPathStr("/foo"); + replacements.SetQueryStr("search"); + replacements.SetRefStr("ref"); + return url.ReplaceComponents(replacements); + }, + .expected = "http://www.google.com:99/foo?search#ref"}, #ifdef WIN32 - {"http://www.google.com/foo/bar.html?foo#bar", "file", "", "", "", "", - "c:\\", "", "", "file:///C:/"}, + {.base = "http://www.google.com/foo/bar.html?foo#bar", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetSchemeStr("file"); + replacements.ClearUsername(); + replacements.ClearPassword(); + replacements.ClearHost(); + replacements.ClearPort(); + replacements.SetPathStr("c:\\"); + replacements.ClearQuery(); + replacements.ClearRef(); + return url.ReplaceComponents(replacements); + }, + .expected = "file:///C:/"}, #endif - {"filesystem:http://www.google.com/foo/bar.html?foo#bar", nullptr, - nullptr, nullptr, nullptr, nullptr, "/", "", "", - "filesystem:http://www.google.com/foo/"}, + {.base = "filesystem:http://www.google.com/foo/bar.html?foo#bar", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetPathStr("/"); + replacements.ClearQuery(); + replacements.ClearRef(); + return url.ReplaceComponents(replacements); + }, + .expected = "filesystem:http://www.google.com/foo/"}, // Lengthen the URL instead of shortening it, to test creation of // inner_url. - {"filesystem:http://www.google.com/foo/", nullptr, nullptr, nullptr, - nullptr, nullptr, "bar.html", "foo", "bar", - "filesystem:http://www.google.com/foo/bar.html?foo#bar"}, + {.base = "filesystem:http://www.google.com/foo/", + .apply_replacements = + +[](const GURL& url) { + GURL::Replacements replacements; + replacements.SetPathStr("bar.html"); + replacements.SetQueryStr("foo"); + replacements.SetRefStr("bar"); + return url.ReplaceComponents(replacements); + }, + .expected = "filesystem:http://www.google.com/foo/bar.html?foo#bar"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { - const ReplaceCase& cur = replace_cases[i]; - GURL url(cur.base); - GURL::Replacements repl; - SetupReplacement(&GURL::Replacements::SetScheme, &repl, cur.scheme); - SetupReplacement(&GURL::Replacements::SetUsername, &repl, cur.username); - SetupReplacement(&GURL::Replacements::SetPassword, &repl, cur.password); - SetupReplacement(&GURL::Replacements::SetHost, &repl, cur.host); - SetupReplacement(&GURL::Replacements::SetPort, &repl, cur.port); - SetupReplacement(&GURL::Replacements::SetPath, &repl, cur.path); - SetupReplacement(&GURL::Replacements::SetQuery, &repl, cur.query); - SetupReplacement(&GURL::Replacements::SetRef, &repl, cur.ref); - GURL output = url.ReplaceComponents(repl); + for (const ReplaceCase& c : replace_cases) { + GURL output = c.apply_replacements(GURL(c.base)); - EXPECT_EQ(replace_cases[i].expected, output.spec()); + EXPECT_EQ(c.expected, output.spec()); EXPECT_EQ(output.SchemeIsFileSystem(), output.inner_url() != NULL); if (output.SchemeIsFileSystem()) { // TODO(mmenke): inner_url()->spec() is currently the same as the spec() // for the GURL itself. This should be fixed. // See https://crbug.com/619596 - EXPECT_EQ(replace_cases[i].expected, output.inner_url()->spec()); + EXPECT_EQ(c.expected, output.inner_url()->spec()); } } } @@ -847,6 +876,20 @@ EXPECT_FALSE(GURL("http://bar/").SchemeIsBlob()); } +TEST(GURLTest, SchemeIsLocal) { + EXPECT_TRUE(GURL("BLOB://BAR/").SchemeIsLocal()); + EXPECT_TRUE(GURL("blob://bar/").SchemeIsLocal()); + EXPECT_TRUE(GURL("DATA:TEXT/HTML,BAR").SchemeIsLocal()); + EXPECT_TRUE(GURL("data:text/html,bar").SchemeIsLocal()); + EXPECT_TRUE(GURL("ABOUT:BAR").SchemeIsLocal()); + EXPECT_TRUE(GURL("about:bar").SchemeIsLocal()); + EXPECT_TRUE(GURL("FILESYSTEM:HTTP://FOO.EXAMPLE/BAR").SchemeIsLocal()); + EXPECT_TRUE(GURL("filesystem:http://foo.example/bar").SchemeIsLocal()); + + EXPECT_FALSE(GURL("http://bar/").SchemeIsLocal()); + EXPECT_FALSE(GURL("file:///bar").SchemeIsLocal()); +} + // Tests that the 'content' of the URL is properly extracted. This can be // complex in cases such as multiple schemes (view-source:http:) or for // javascript URLs. See GURL::GetContent for more details.
diff --git a/url/origin.cc b/url/origin.cc index 6c7915f..e943d4f 100644 --- a/url/origin.cc +++ b/url/origin.cc
@@ -60,7 +60,7 @@ } Origin Origin::Resolve(const GURL& url, const Origin& base_origin) { - if (url.SchemeIs(kAboutScheme)) + if (url.SchemeIs(kAboutScheme) || url.is_empty()) return base_origin; Origin result = Origin::Create(url); if (!result.opaque()) @@ -163,6 +163,20 @@ return std::tie(tuple_, nonce_) == std::tie(other.tuple_, other.nonce_); } +bool Origin::IsSameOriginWith(const GURL& url) const { + if (opaque()) + return false; + + // The `url::Origin::Create` call here preserves how IsSameOriginWith was used + // historically, even though in some scenarios it is not clearly correct: + // - Origin of about:blank and about:srcdoc cannot be correctly + // computed/recovered. + // - Ideally passing an invalid `url` would be a caller error (e.g. a GURL_DCHECK). + // - The caller intent is not always clear wrt handling the outer-vs-inner + // origins/URLs in blob: and filesystem: schemes. + return IsSameOriginWith(url::Origin::Create(url)); +} + bool Origin::CanBeDerivedFrom(const GURL& url) const { GURL_DCHECK(url.is_valid()); @@ -456,7 +470,7 @@ ScopedOriginCrashKey::ScopedOriginCrashKey( gurl_base::debug::CrashKeyString* crash_key, const url::Origin* value) - : gurl_base::debug::ScopedCrashKeyString( + : scoped_string_value_( crash_key, value ? value->GetDebugString(false /* include_nonce */) : "nullptr") {}
diff --git a/url/origin.h b/url/origin.h index bfd3b36..c1ad177 100644 --- a/url/origin.h +++ b/url/origin.h
@@ -25,7 +25,7 @@ #include "url/url_canon.h" #include "url/url_constants.h" -#if defined(OS_ANDROID) +#if BUILDFLAG(IS_ANDROID) #include <jni.h> namespace gurl_base { @@ -36,12 +36,13 @@ class JavaRef; } // namespace android } // namespace base -#endif // OS_ANDROID +#endif // BUILDFLAG(IS_ANDROID) class GURL; namespace blink { class SecurityOrigin; +class SecurityOriginTest; } // namespace blink namespace ipc_fuzzer { @@ -222,6 +223,15 @@ return !IsSameOriginWith(other); } + // Non-opaque origin is "same-origin" with `url` if their schemes, hosts, and + // ports are exact matches. Opaque origin is never "same-origin" with any + // `url`. about:blank, about:srcdoc, and invalid GURLs are never + // "same-origin" with any origin. This method is a shorthand for + // `origin.IsSameOriginWith(url::Origin::Create(url))`. + // + // See also CanBeDerivedFrom. + bool IsSameOriginWith(const GURL& url) const; + // This method returns true for any |url| which if navigated to could result // in an origin compatible with |this|. bool CanBeDerivedFrom(const GURL& url) const; @@ -289,16 +299,17 @@ // and precursor information. std::string GetDebugString(bool include_nonce = true) const; -#if defined(OS_ANDROID) +#if BUILDFLAG(IS_ANDROID) gurl_base::android::ScopedJavaLocalRef<jobject> CreateJavaObject() const; static Origin FromJavaObject( const gurl_base::android::JavaRef<jobject>& java_origin); -#endif // OS_ANDROID +#endif // BUILDFLAG(IS_ANDROID) void WriteIntoTrace(perfetto::TracedValue context) const; private: friend class blink::SecurityOrigin; + friend class blink::SecurityOriginTest; // SchemefulSite needs access to the serialization/deserialization logic which // includes the nonce. friend class net::SchemefulSite; @@ -440,8 +451,7 @@ namespace debug { -class COMPONENT_EXPORT(URL) ScopedOriginCrashKey - : public gurl_base::debug::ScopedCrashKeyString { +class COMPONENT_EXPORT(URL) ScopedOriginCrashKey { public: ScopedOriginCrashKey(gurl_base::debug::CrashKeyString* crash_key, const url::Origin* value); @@ -449,6 +459,9 @@ ScopedOriginCrashKey(const ScopedOriginCrashKey&) = delete; ScopedOriginCrashKey& operator=(const ScopedOriginCrashKey&) = delete; + + private: + gurl_base::debug::ScopedCrashKeyString scoped_string_value_; }; } // namespace debug
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc index cb78bb6..755d2e3 100644 --- a/url/origin_unittest.cc +++ b/url/origin_unittest.cc
@@ -5,7 +5,7 @@ #include <stddef.h> #include <stdint.h> -#include "base/macros.h" +#include "base/memory/raw_ptr.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -172,6 +172,7 @@ EXPECT_LT(opaque_a, url::Origin::Create(GURL("http://www.google.com"))); EXPECT_LT(opaque_b, url::Origin::Create(GURL("http://www.google.com"))); + EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL(), opaque_b)); EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL("about:blank"), opaque_b)); EXPECT_EQ(opaque_b, url::Origin::Resolve(GURL("about:srcdoc"), opaque_b)); EXPECT_EQ(opaque_b, @@ -495,7 +496,7 @@ // and ensure that it returns |expected_value| const struct { const char* url; - Origin* origin; + raw_ptr<Origin> origin; bool expected_value; } kTestCases[] = { {"https://a.com", ®ular_origin, true}, @@ -746,6 +747,29 @@ EXPECT_EQ(opaque.GetDebugString(), deserialized.value().GetDebugString()); } +TEST_F(OriginTest, IsSameOriginWith) { + url::Origin opaque_origin; + GURL foo_url = GURL("https://foo.com/path"); + url::Origin foo_origin = url::Origin::Create(foo_url); + GURL bar_url = GURL("https://bar.com/path"); + url::Origin bar_origin = url::Origin::Create(bar_url); + + EXPECT_FALSE(opaque_origin.IsSameOriginWith(foo_origin)); + EXPECT_FALSE(opaque_origin.IsSameOriginWith(foo_url)); + + EXPECT_TRUE(foo_origin.IsSameOriginWith(foo_origin)); + EXPECT_TRUE(foo_origin.IsSameOriginWith(foo_url)); + + EXPECT_FALSE(foo_origin.IsSameOriginWith(bar_origin)); + EXPECT_FALSE(foo_origin.IsSameOriginWith(bar_url)); + + // Documenting legacy behavior. This doesn't necessarily mean that the legacy + // behavior is correct (or desirable in the long-term). + EXPECT_FALSE(foo_origin.IsSameOriginWith(GURL("about:blank"))); + EXPECT_FALSE(foo_origin.IsSameOriginWith(GURL())); // Invalid GURL. + EXPECT_TRUE(foo_origin.IsSameOriginWith(GURL("blob:https://foo.com/guid"))); +} + INSTANTIATE_TYPED_TEST_SUITE_P(UrlOrigin, AbstractOriginTest, UrlOriginTestTraits);
diff --git a/url/run_all_unittests.cc b/url/run_all_unittests.cc index 0f6a431..cf408d4 100644 --- a/url/run_all_unittests.cc +++ b/url/run_all_unittests.cc
@@ -10,14 +10,14 @@ #include "base/test/test_suite.h" #include "build/build_config.h" -#if !defined(OS_IOS) +#if !BUILDFLAG(IS_IOS) #include "mojo/core/embedder/embedder.h" // nogncheck #endif int main(int argc, char** argv) { gurl_base::TestSuite test_suite(argc, argv); -#if !defined(OS_IOS) +#if !BUILDFLAG(IS_IOS) mojo::core::Init(); #endif
diff --git a/url/scheme_host_port.cc b/url/scheme_host_port.cc index c337da3..854c6f6 100644 --- a/url/scheme_host_port.cc +++ b/url/scheme_host_port.cc
@@ -7,6 +7,7 @@ #include <stdint.h> #include <string.h> +#include <ostream> #include <tuple> #include "polyfills/base/check_op.h"
diff --git a/url/url_canon.h b/url/url_canon.h index 457f58a..32e7b15 100644 --- a/url/url_canon.h +++ b/url/url_canon.h
@@ -139,6 +139,8 @@ return true; } + // `buffer_` is not a raw_ptr<...> for performance reasons (based on analysis + // of sampling profiler data). T* buffer_; int buffer_len_;
diff --git a/url/url_canon_host.cc b/url/url_canon_host.cc index 7a97522..370dd77 100644 --- a/url/url_canon_host.cc +++ b/url/url_canon_host.cc
@@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <unordered_set> - #include "polyfills/base/check.h" -#include "polyfills/base/metrics/histogram_macros.h" +#include "polyfills/base/cpu_reduction_experiment.h" #include "url/url_canon.h" #include "url/url_canon_internal.h" @@ -132,8 +130,6 @@ bool* has_non_ascii) { *has_non_ascii = false; - std::unordered_set<char> escaped_chars_to_measure; - bool success = true; for (int i = 0; i < host_len; ++i) { unsigned int source = host[i]; @@ -161,7 +157,6 @@ } else if (replacement == kEsc) { // This character is valid but should be escaped. AppendEscapedChar(source, output); - escaped_chars_to_measure.insert(source); } else { // Common case, the given character is valid in a hostname, the lookup // table tells us the canonical representation of that character (lower @@ -176,16 +171,6 @@ *has_non_ascii = true; } } - if (success) { - bool did_escape = !escaped_chars_to_measure.empty(); - UMA_HISTOGRAM_BOOLEAN("URL.Host.DidEscape", did_escape); - if (did_escape) { - for (char c : escaped_chars_to_measure) { - UMA_HISTOGRAM_ENUMERATION("URL.Host.EscapeChar", - EscapedHostCharToEnum(c)); - } - } - } return success; }
diff --git a/url/url_canon_icu.cc b/url/url_canon_icu.cc index b4f8f81..3a6b9be 100644 --- a/url/url_canon_icu.cc +++ b/url/url_canon_icu.cc
@@ -9,6 +9,7 @@ #include <string.h> #include "polyfills/base/check.h" +#include "base/memory/raw_ptr.h" #include <unicode/ucnv.h> #include <unicode/ucnv_cb.h> #include <unicode/utypes.h> @@ -66,7 +67,7 @@ } private: - UConverter* converter_; + raw_ptr<UConverter> converter_; UConverterFromUCallback old_callback_; const void* old_context_;
diff --git a/url/url_canon_icu.h b/url/url_canon_icu.h index 34bb99e..b861f7a 100644 --- a/url/url_canon_icu.h +++ b/url/url_canon_icu.h
@@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "polyfills/base/component_export.h" +#include "base/memory/raw_ptr.h" #include "url/url_canon.h" typedef struct UConverter UConverter; @@ -32,7 +33,7 @@ private: // The ICU converter, not owned by this class. - UConverter* converter_; + raw_ptr<UConverter> converter_; }; } // namespace url
diff --git a/url/url_canon_icu_unittest.cc b/url/url_canon_icu_unittest.cc index ca13427..702b1d3 100644 --- a/url/url_canon_icu_unittest.cc +++ b/url/url_canon_icu_unittest.cc
@@ -6,6 +6,7 @@ #include "base/cxx17_backports.h" #include "polyfills/base/logging.h" +#include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include <unicode/ucnv.h> #include "url/url_canon.h" @@ -38,7 +39,7 @@ UConverter* converter() const { return converter_; } private: - UConverter* converter_; + raw_ptr<UConverter> converter_; }; TEST(URLCanonIcuTest, ICUCharsetConverter) {
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc index 961a3be..99541bd 100644 --- a/url/url_canon_internal.cc +++ b/url/url_canon_internal.cc
@@ -435,49 +435,4 @@ #endif // !WIN32 -EscapedHostChar EscapedHostCharToEnum(char c) { - switch (c) { - case ' ': - return EscapedHostChar::kSpace; - case '!': - return EscapedHostChar::kBang; - case '"': - return EscapedHostChar::kDoubleQuote; - case '#': - return EscapedHostChar::kHash; - case '$': - return EscapedHostChar::kDollar; - case '&': - return EscapedHostChar::kAmpersand; - case '\'': - return EscapedHostChar::kSingleQuote; - case '(': - return EscapedHostChar::kLeftParen; - case ')': - return EscapedHostChar::kRightParen; - case '*': - return EscapedHostChar::kAsterisk; - case ',': - return EscapedHostChar::kComma; - case '<': - return EscapedHostChar::kLeftAngle; - case '=': - return EscapedHostChar::kEquals; - case '>': - return EscapedHostChar::kRightAngle; - case '@': - return EscapedHostChar::kAt; - case '`': - return EscapedHostChar::kBackTick; - case '{': - return EscapedHostChar::kLeftCurly; - case '|': - return EscapedHostChar::kPipe; - case '}': - return EscapedHostChar::kRightCurly; - default: - return EscapedHostChar::kUnknown; - } -} - } // namespace url
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h index 6601587..d674976 100644 --- a/url/url_canon_internal.h +++ b/url/url_canon_internal.h
@@ -456,35 +456,6 @@ #endif // WIN32 -// These values are logged to UMA. Entries should not be renumbered and -// numeric values should never be reused. Please keep in sync with -// "URLHostEscapedHostChar" in src/tools/metrics/histograms/enums.xml. -enum class EscapedHostChar { - kUnknown = 0, - kSpace = 1, - kBang = 2, - kDoubleQuote = 3, - kHash = 4, - kDollar = 5, - kAmpersand = 6, - kSingleQuote = 7, - kLeftParen = 8, - kRightParen = 9, - kAsterisk = 10, - kComma = 11, - kLeftAngle = 12, - kEquals = 13, - kRightAngle = 14, - kAt = 15, - kBackTick = 16, - kLeftCurly = 17, - kPipe = 18, - kRightCurly = 19, - kMaxValue = kRightCurly, -}; - -COMPONENT_EXPORT(URL) EscapedHostChar EscapedHostCharToEnum(char c); - } // namespace url #endif // URL_URL_CANON_INTERNAL_H_
diff --git a/url/url_canon_stdstring.h b/url/url_canon_stdstring.h index cef33cd..e9adc43 100644 --- a/url/url_canon_stdstring.h +++ b/url/url_canon_stdstring.h
@@ -13,7 +13,6 @@ #include "base/compiler_specific.h" #include "polyfills/base/component_export.h" -#include "base/macros.h" #include "base/strings/string_piece.h" #include "url/url_canon.h" @@ -49,6 +48,8 @@ void Resize(int sz) override; protected: + // `str_` is not a raw_ptr<...> for performance reasons (based on analysis of + // sampling profiler data and tab_search:top100:2020). std::string* str_; }; @@ -82,30 +83,47 @@ void SetUsernameStr(const CharT* str) { SetImpl(&ParentT::SetUsername, str); } void SetUsernameStr(StringPieceT str) { SetImpl(&ParentT::SetUsername, str); } void SetUsernameStr(const StringT&&) = delete; + using ParentT::ClearUsername; void SetPasswordStr(const CharT* str) { SetImpl(&ParentT::SetPassword, str); } void SetPasswordStr(StringPieceT str) { SetImpl(&ParentT::SetPassword, str); } void SetPasswordStr(const StringT&&) = delete; + using ParentT::ClearPassword; void SetHostStr(const CharT* str) { SetImpl(&ParentT::SetHost, str); } void SetHostStr(StringPieceT str) { SetImpl(&ParentT::SetHost, str); } void SetHostStr(const StringT&&) = delete; + using ParentT::ClearHost; void SetPortStr(const CharT* str) { SetImpl(&ParentT::SetPort, str); } void SetPortStr(StringPieceT str) { SetImpl(&ParentT::SetPort, str); } void SetPortStr(const StringT&&) = delete; + using ParentT::ClearPort; void SetPathStr(const CharT* str) { SetImpl(&ParentT::SetPath, str); } void SetPathStr(StringPieceT str) { SetImpl(&ParentT::SetPath, str); } void SetPathStr(const StringT&&) = delete; + using ParentT::ClearPath; void SetQueryStr(const CharT* str) { SetImpl(&ParentT::SetQuery, str); } void SetQueryStr(StringPieceT str) { SetImpl(&ParentT::SetQuery, str); } void SetQueryStr(const StringT&&) = delete; + using ParentT::ClearQuery; void SetRefStr(const CharT* str) { SetImpl(&ParentT::SetRef, str); } void SetRefStr(StringPieceT str) { SetImpl(&ParentT::SetRef, str); } void SetRefStr(const StringT&&) = delete; + using ParentT::ClearRef; + + private: + using ParentT::SetHost; + using ParentT::SetPassword; + using ParentT::SetPath; + using ParentT::SetPort; + using ParentT::SetQuery; + using ParentT::SetRef; + using ParentT::SetScheme; + using ParentT::SetUsername; }; } // namespace url
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index d7dc876..2dd5075 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -9,7 +9,6 @@ #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/test/gtest_util.h" -#include "base/test/metrics/histogram_tester.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/third_party/mozilla/url_parse.h" #include "url/url_canon.h" @@ -2609,49 +2608,4 @@ output.set_length(0); } -TEST(URLCanonTest, EscapedHostCharToEnum) { - EXPECT_EQ(EscapedHostChar::kSpace, EscapedHostCharToEnum(' ')); - EXPECT_EQ(EscapedHostChar::kBang, EscapedHostCharToEnum('!')); - EXPECT_EQ(EscapedHostChar::kDoubleQuote, EscapedHostCharToEnum('"')); - EXPECT_EQ(EscapedHostChar::kHash, EscapedHostCharToEnum('#')); - EXPECT_EQ(EscapedHostChar::kDollar, EscapedHostCharToEnum('$')); - EXPECT_EQ(EscapedHostChar::kAmpersand, EscapedHostCharToEnum('&')); - EXPECT_EQ(EscapedHostChar::kSingleQuote, EscapedHostCharToEnum('\'')); - EXPECT_EQ(EscapedHostChar::kLeftParen, EscapedHostCharToEnum('(')); - EXPECT_EQ(EscapedHostChar::kRightParen, EscapedHostCharToEnum(')')); - EXPECT_EQ(EscapedHostChar::kAsterisk, EscapedHostCharToEnum('*')); - EXPECT_EQ(EscapedHostChar::kComma, EscapedHostCharToEnum(',')); - EXPECT_EQ(EscapedHostChar::kLeftAngle, EscapedHostCharToEnum('<')); - EXPECT_EQ(EscapedHostChar::kEquals, EscapedHostCharToEnum('=')); - EXPECT_EQ(EscapedHostChar::kRightAngle, EscapedHostCharToEnum('>')); - EXPECT_EQ(EscapedHostChar::kAt, EscapedHostCharToEnum('@')); - EXPECT_EQ(EscapedHostChar::kBackTick, EscapedHostCharToEnum('`')); - EXPECT_EQ(EscapedHostChar::kLeftCurly, EscapedHostCharToEnum('{')); - EXPECT_EQ(EscapedHostChar::kPipe, EscapedHostCharToEnum('|')); - EXPECT_EQ(EscapedHostChar::kRightCurly, EscapedHostCharToEnum('}')); - - EXPECT_EQ(EscapedHostChar::kUnknown, EscapedHostCharToEnum('a')); - EXPECT_EQ(EscapedHostChar::kUnknown, EscapedHostCharToEnum('\\')); -} - -TEST(URLCanonTest, EscapedHostCharHistograms) { - std::string input("foo <bar>"); - - Component in_comp(0, input.size()); - Component out_comp; - std::string out_str; - StdStringCanonOutput output(&out_str); - - gurl_base::HistogramTester histogram_tester; - bool success = CanonicalizeHost(input.data(), in_comp, &output, &out_comp); - ASSERT_TRUE(success); - histogram_tester.ExpectBucketCount("URL.Host.DidEscape", 1, 1); - histogram_tester.ExpectBucketCount("URL.Host.EscapeChar", - EscapedHostChar::kSpace, 1); - histogram_tester.ExpectBucketCount("URL.Host.EscapeChar", - EscapedHostChar::kLeftAngle, 1); - histogram_tester.ExpectBucketCount("URL.Host.EscapeChar", - EscapedHostChar::kRightAngle, 1); -} - } // namespace url
diff --git a/url/url_constants.cc b/url/url_constants.cc index d7a5de7..9685098 100644 --- a/url/url_constants.cc +++ b/url/url_constants.cc
@@ -7,33 +7,56 @@ namespace url { const char kAboutBlankURL[] = "about:blank"; +const char16_t kAboutBlankURL16[] = u"about:blank"; const char kAboutSrcdocURL[] = "about:srcdoc"; +const char16_t kAboutSrcdocURL16[] = u"about:srcdoc"; const char kAboutBlankPath[] = "blank"; +const char16_t kAboutBlankPath16[] = u"blank"; const char kAboutSrcdocPath[] = "srcdoc"; +const char16_t kAboutSrcdocPath16[] = u"srcdoc"; const char kAboutScheme[] = "about"; +const char16_t kAboutScheme16[] = u"about"; const char kBlobScheme[] = "blob"; +const char16_t kBlobScheme16[] = u"blob"; const char kContentScheme[] = "content"; +const char16_t kContentScheme16[] = u"content"; const char kContentIDScheme[] = "cid"; +const char16_t kContentIDScheme16[] = u"cid"; const char kDataScheme[] = "data"; +const char16_t kDataScheme16[] = u"data"; const char kFileScheme[] = "file"; +const char16_t kFileScheme16[] = u"file"; const char kFileSystemScheme[] = "filesystem"; +const char16_t kFileSystemScheme16[] = u"filesystem"; const char kFtpScheme[] = "ftp"; +const char16_t kFtpScheme16[] = u"ftp"; const char kHttpScheme[] = "http"; +const char16_t kHttpScheme16[] = u"http"; const char kHttpsScheme[] = "https"; +const char16_t kHttpsScheme16[] = u"https"; const char kJavaScriptScheme[] = "javascript"; +const char16_t kJavaScriptScheme16[] = u"javascript"; const char kMailToScheme[] = "mailto"; +const char16_t kMailToScheme16[] = u"mailto"; // This is for QuicTransport (https://wicg.github.io/web-transport/). // See also: https://www.iana.org/assignments/uri-schemes/prov/quic-transport const char kQuicTransportScheme[] = "quic-transport"; +const char16_t kQuicTransportScheme16[] = u"quic-transport"; const char kTelScheme[] = "tel"; +const char16_t kTelScheme16[] = u"tel"; const char kUrnScheme[] = "urn"; +const char16_t kUrnScheme16[] = u"urn"; const char kUuidInPackageScheme[] = "uuid-in-package"; +const char16_t kUuidInPackageScheme16[] = u"uuid-in-package"; const char kWsScheme[] = "ws"; +const char16_t kWsScheme16[] = u"ws"; const char kWssScheme[] = "wss"; +const char16_t kWssScheme16[] = u"wss"; const char kStandardSchemeSeparator[] = "://"; +const char16_t kStandardSchemeSeparator16[] = u"://"; const size_t kMaxURLChars = 2 * 1024 * 1024;
diff --git a/url/url_constants.h b/url/url_constants.h index 69a72f5..b4a5889 100644 --- a/url/url_constants.h +++ b/url/url_constants.h
@@ -12,33 +12,56 @@ namespace url { COMPONENT_EXPORT(URL) extern const char kAboutBlankURL[]; +COMPONENT_EXPORT(URL) extern const char16_t kAboutBlankURL16[]; COMPONENT_EXPORT(URL) extern const char kAboutSrcdocURL[]; +COMPONENT_EXPORT(URL) extern const char16_t kAboutSrcdocURL16[]; COMPONENT_EXPORT(URL) extern const char kAboutBlankPath[]; +COMPONENT_EXPORT(URL) extern const char16_t kAboutBlankPath16[]; COMPONENT_EXPORT(URL) extern const char kAboutSrcdocPath[]; +COMPONENT_EXPORT(URL) extern const char16_t kAboutSrcdocPath16[]; COMPONENT_EXPORT(URL) extern const char kAboutScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kAboutScheme16[]; COMPONENT_EXPORT(URL) extern const char kBlobScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kBlobScheme16[]; // The content scheme is specific to Android for identifying a stored file. COMPONENT_EXPORT(URL) extern const char kContentScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kContentScheme16[]; COMPONENT_EXPORT(URL) extern const char kContentIDScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kContentIDScheme16[]; COMPONENT_EXPORT(URL) extern const char kDataScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kDataScheme16[]; COMPONENT_EXPORT(URL) extern const char kFileScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kFileScheme16[]; COMPONENT_EXPORT(URL) extern const char kFileSystemScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kFileSystemScheme16[]; COMPONENT_EXPORT(URL) extern const char kFtpScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kFtpScheme16[]; COMPONENT_EXPORT(URL) extern const char kHttpScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kHttpScheme16[]; COMPONENT_EXPORT(URL) extern const char kHttpsScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kHttpsScheme16[]; COMPONENT_EXPORT(URL) extern const char kJavaScriptScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kJavaScriptScheme16[]; COMPONENT_EXPORT(URL) extern const char kMailToScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kMailToScheme16[]; COMPONENT_EXPORT(URL) extern const char kQuicTransportScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kQuicTransportScheme16[]; COMPONENT_EXPORT(URL) extern const char kTelScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kTelScheme16[]; COMPONENT_EXPORT(URL) extern const char kUrnScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kUrnScheme16[]; COMPONENT_EXPORT(URL) extern const char kUuidInPackageScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kUuidInPackageScheme16[]; COMPONENT_EXPORT(URL) extern const char kWsScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kWsScheme16[]; COMPONENT_EXPORT(URL) extern const char kWssScheme[]; +COMPONENT_EXPORT(URL) extern const char16_t kWssScheme16[]; // Used to separate a standard scheme and the hostname: "://". COMPONENT_EXPORT(URL) extern const char kStandardSchemeSeparator[]; +COMPONENT_EXPORT(URL) extern const char16_t kStandardSchemeSeparator16[]; COMPONENT_EXPORT(URL) extern const size_t kMaxURLChars;
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc index a455ff6..5255817 100644 --- a/url/url_util_unittest.cc +++ b/url/url_util_unittest.cc
@@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "url/url_util.h" + #include <stddef.h> #include "base/cxx17_backports.h" #include "base/strings/string_piece.h" +#include "build/build_config.h" #include "testing/gtest/include/gtest/gtest-message.h" #include "testing/gtest/include/gtest/gtest.h" #include "absl/types/optional.h" @@ -13,7 +16,6 @@ #include "url/url_canon.h" #include "url/url_canon_stdstring.h" #include "url/url_test_utils.h" -#include "url/url_util.h" namespace url { @@ -574,7 +576,7 @@ } } // namespace -#ifdef OS_WIN +#if BUILDFLAG(IS_WIN) // Regression test for https://crbug.com/1252658. TEST_F(URLUtilTest, TestCanonicalizeWindowsPathWithLeadingNUL) { auto PrefixWithNUL = [](std::string&& s) -> std::string { return '\0' + s; };