feat_allow_code_cache_in_custom_schemes.patch 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Cheng Zhao <[email protected]>
  3. Date: Thu, 14 Dec 2023 21:16:53 +0900
  4. Subject: Enable V8 code cache for custom schemes
  5. Add a new category in ContentClient::AddAdditionalSchemes which allows
  6. embedders to make custom schemes allow V8 code cache.
  7. Chromium CL: https://chromium-review.googlesource.com/c/chromium/src/+/5019665
  8. diff --git a/content/browser/code_cache/generated_code_cache.cc b/content/browser/code_cache/generated_code_cache.cc
  9. index d9e3751608d19adc82bf67959a44926852d8eb85..3ad5a73c1326e4f9333d4f1af90bdd064e4024dd 100644
  10. --- a/content/browser/code_cache/generated_code_cache.cc
  11. +++ b/content/browser/code_cache/generated_code_cache.cc
  12. @@ -12,6 +12,7 @@
  13. #include <iostream>
  14. #include <string_view>
  15. +#include "base/containers/contains.h"
  16. #include "base/feature_list.h"
  17. #include "base/functional/bind.h"
  18. #include "base/functional/callback_helpers.h"
  19. @@ -36,6 +37,7 @@
  20. #include "net/http/http_cache.h"
  21. #include "third_party/blink/public/common/scheme_registry.h"
  22. #include "url/gurl.h"
  23. +#include "url/url_util.h"
  24. using storage::BigIOBuffer;
  25. @@ -48,7 +50,7 @@ constexpr char kSeparator[] = " \n";
  26. // We always expect to receive valid URLs that can be used as keys to the code
  27. // cache. The relevant checks (for ex: resource_url is valid, origin_lock is
  28. -// not opque etc.,) must be done prior to requesting the code cache.
  29. +// not opaque etc.,) must be done prior to requesting the code cache.
  30. //
  31. // This function doesn't enforce anything in the production code. It is here
  32. // to make the assumptions explicit and to catch any errors when DCHECKs are
  33. @@ -58,33 +60,55 @@ void CheckValidKeys(const GURL& resource_url,
  34. GeneratedCodeCache::CodeCacheType cache_type) {
  35. // If the resource url is invalid don't cache the code.
  36. DCHECK(resource_url.is_valid());
  37. - bool resource_url_is_chrome_or_chrome_untrusted =
  38. +
  39. + // There are 3 kind of URL scheme compatible for the `resource_url`.
  40. + // 1. http: and https: URLs.
  41. + // 2. chrome: and chrome-untrusted: URLs.
  42. + // 3. URLs whose scheme are allowed by the content/ embedder.
  43. + const bool resource_url_http = resource_url.SchemeIsHTTPOrHTTPS();
  44. + const bool resource_url_webui =
  45. resource_url.SchemeIs(content::kChromeUIScheme) ||
  46. resource_url.SchemeIs(content::kChromeUIUntrustedScheme);
  47. - DCHECK(resource_url.SchemeIsHTTPOrHTTPS() ||
  48. - resource_url_is_chrome_or_chrome_untrusted ||
  49. - blink::CommonSchemeRegistry::IsExtensionScheme(resource_url.scheme()));
  50. -
  51. - // |origin_lock| should be either empty or should have
  52. - // Http/Https/chrome/chrome-untrusted schemes and it should not be a URL with
  53. - // opaque origin. Empty origin_locks are allowed when the renderer is not
  54. - // locked to an origin.
  55. - bool origin_lock_is_chrome_or_chrome_untrusted =
  56. +
  57. + const bool resource_url_embedder =
  58. + base::Contains(url::GetCodeCacheSchemes(), resource_url.scheme());
  59. + DCHECK(resource_url_http || resource_url_webui || resource_url_embedder);
  60. +
  61. + // |origin_lock| should be either empty or should have code cache allowed
  62. + // schemes (http/https/chrome/chrome-untrusted or other custom schemes added
  63. + // by url::AddCodeCacheScheme), and it should not be a URL with opaque
  64. + // origin. Empty origin_locks are allowed when the renderer is not locked to
  65. + // an origin.
  66. + const bool origin_lock_empty = origin_lock.is_empty();
  67. + const bool origin_lock_for_http = origin_lock.SchemeIsHTTPOrHTTPS();
  68. + const bool origin_lock_for_webui =
  69. origin_lock.SchemeIs(content::kChromeUIScheme) ||
  70. origin_lock.SchemeIs(content::kChromeUIUntrustedScheme);
  71. - DCHECK(
  72. - origin_lock.is_empty() ||
  73. - ((origin_lock.SchemeIsHTTPOrHTTPS() ||
  74. - origin_lock_is_chrome_or_chrome_untrusted ||
  75. - blink::CommonSchemeRegistry::IsExtensionScheme(origin_lock.scheme())) &&
  76. - !url::Origin::Create(origin_lock).opaque()));
  77. -
  78. - // The chrome and chrome-untrusted schemes are only used with the WebUI
  79. - // code cache type.
  80. - DCHECK_EQ(origin_lock_is_chrome_or_chrome_untrusted,
  81. - cache_type == GeneratedCodeCache::kWebUIJavaScript);
  82. - DCHECK_EQ(resource_url_is_chrome_or_chrome_untrusted,
  83. - cache_type == GeneratedCodeCache::kWebUIJavaScript);
  84. + const bool origin_lock_for_embedder =
  85. + base::Contains(url::GetCodeCacheSchemes(), origin_lock.scheme());
  86. +
  87. + DCHECK(origin_lock_empty || ((origin_lock_for_http || origin_lock_for_webui ||
  88. + origin_lock_for_embedder) &&
  89. + !url::Origin::Create(origin_lock).opaque()));
  90. +
  91. + // The webui schemes are only used with their dedicated code cache type.
  92. + switch (cache_type) {
  93. + case GeneratedCodeCache::kJavaScript:
  94. + case GeneratedCodeCache::kWebAssembly:
  95. + DCHECK(!origin_lock_for_webui);
  96. + DCHECK(!resource_url_webui);
  97. + break;
  98. + case GeneratedCodeCache::kWebUIJavaScript:
  99. + DCHECK(origin_lock_for_webui);
  100. + DCHECK(resource_url_webui);
  101. + break;
  102. + }
  103. +
  104. + // The custom schemes share the cache type with http(s).
  105. + if (origin_lock_for_embedder || resource_url_embedder) {
  106. + DCHECK(cache_type == GeneratedCodeCache::kJavaScript ||
  107. + cache_type == GeneratedCodeCache::kWebAssembly);
  108. + }
  109. }
  110. // Generates the cache key for the given |resource_url|, |origin_lock| and
  111. diff --git a/content/browser/code_cache/generated_code_cache.h b/content/browser/code_cache/generated_code_cache.h
  112. index e0cdc785d2557bc79bde98728c23c239ed8d0961..74e0acbea1e0c18a6ac8971170efc945ca58f4ed 100644
  113. --- a/content/browser/code_cache/generated_code_cache.h
  114. +++ b/content/browser/code_cache/generated_code_cache.h
  115. @@ -52,12 +52,14 @@ class CONTENT_EXPORT GeneratedCodeCache {
  116. // Cache type. Used for collecting statistics for JS and Wasm in separate
  117. // buckets.
  118. enum CodeCacheType {
  119. - // JavaScript from http(s) pages.
  120. + // JavaScript from pages of http(s) schemes or custom schemes registered by
  121. + // url::AddCodeCacheScheme.
  122. kJavaScript,
  123. - // WebAssembly from http(s) pages. This cache allows more total size and
  124. - // more size per item than the JavaScript cache, since some
  125. - // WebAssembly programs are very large.
  126. + // WebAssembly from pages of http(s) schemes or custom schemes registered by
  127. + // url::AddCodeCacheScheme. This cache allows more total size and more size
  128. + // per item than the JavaScript cache, since some WebAssembly programs are
  129. + // very large.
  130. kWebAssembly,
  131. // JavaScript from chrome and chrome-untrusted pages. The resource URLs are
  132. diff --git a/content/browser/code_cache/generated_code_cache_browsertest.cc b/content/browser/code_cache/generated_code_cache_browsertest.cc
  133. index b6dd7405a5c9275ab699d4b347759427b30ef594..253918a2e54c98ce0075bce4e1a52134032ce367 100644
  134. --- a/content/browser/code_cache/generated_code_cache_browsertest.cc
  135. +++ b/content/browser/code_cache/generated_code_cache_browsertest.cc
  136. @@ -8,13 +8,18 @@
  137. #include "content/browser/code_cache/generated_code_cache.h"
  138. #include "content/browser/code_cache/generated_code_cache_context.h"
  139. #include "content/browser/renderer_host/code_cache_host_impl.h"
  140. +#include "content/browser/storage_partition_impl.h"
  141. +#include "content/common/url_schemes.h"
  142. #include "content/public/browser/browser_context.h"
  143. +#include "content/public/browser/browser_thread.h"
  144. #include "content/public/browser/storage_partition.h"
  145. #include "content/public/test/browser_test.h"
  146. #include "content/public/test/browser_test_utils.h"
  147. #include "content/public/test/content_browser_test.h"
  148. #include "content/public/test/content_browser_test_utils.h"
  149. +#include "content/public/test/test_browser_context.h"
  150. #include "content/shell/browser/shell.h"
  151. +#include "content/test/test_content_client.h"
  152. #include "net/dns/mock_host_resolver.h"
  153. #include "third_party/blink/public/common/features.h"
  154. #include "third_party/blink/public/common/page/v8_compile_hints_histograms.h"
  155. @@ -23,6 +28,8 @@ namespace content {
  156. namespace {
  157. +const std::string kCodeCacheScheme = "test-code-cache";
  158. +
  159. bool SupportsSharedWorker() {
  160. #if BUILDFLAG(IS_ANDROID)
  161. // SharedWorkers are not enabled on Android. https://crbug.com/154571
  162. @@ -714,4 +721,82 @@ IN_PROC_BROWSER_TEST_F(LocalCompileHintsBrowserTest, LocalCompileHints) {
  163. }
  164. }
  165. +class CodeCacheInCustomSchemeBrowserTest : public ContentBrowserTest,
  166. + public TestContentClient {
  167. + public:
  168. + CodeCacheInCustomSchemeBrowserTest() {
  169. + SetContentClient(this);
  170. + ReRegisterContentSchemesForTests();
  171. + }
  172. +
  173. + ~CodeCacheInCustomSchemeBrowserTest() override { SetContentClient(nullptr); }
  174. +
  175. + private:
  176. + void AddAdditionalSchemes(Schemes* schemes) override {
  177. + schemes->standard_schemes.push_back(kCodeCacheScheme);
  178. + schemes->code_cache_schemes.push_back(kCodeCacheScheme);
  179. + }
  180. +
  181. + url::ScopedSchemeRegistryForTests scheme_registry_;
  182. +};
  183. +
  184. +IN_PROC_BROWSER_TEST_F(CodeCacheInCustomSchemeBrowserTest,
  185. + AllowedCustomSchemeCanGenerateCodeCache) {
  186. + StoragePartitionImpl* partition =
  187. + static_cast<StoragePartitionImpl*>(shell()
  188. + ->web_contents()
  189. + ->GetBrowserContext()
  190. + ->GetDefaultStoragePartition());
  191. + scoped_refptr<GeneratedCodeCacheContext> context =
  192. + partition->GetGeneratedCodeCacheContext();
  193. + EXPECT_NE(context, nullptr);
  194. +
  195. + GURL url(kCodeCacheScheme + "://host4/script.js");
  196. + GURL origin(kCodeCacheScheme + "://host1:1/");
  197. + ASSERT_TRUE(url.is_valid());
  198. + ASSERT_TRUE(origin.is_valid());
  199. + std::string data("SomeData");
  200. +
  201. + // Add a code cache entry for the custom scheme.
  202. + base::test::TestFuture<void> add_entry_future;
  203. + GeneratedCodeCacheContext::RunOrPostTask(
  204. + context.get(), FROM_HERE,
  205. + base::BindOnce(
  206. + [](scoped_refptr<GeneratedCodeCacheContext> context, const GURL& url,
  207. + const GURL& origin, const std::string& data,
  208. + base::OnceClosure callback) {
  209. + context->generated_js_code_cache()->WriteEntry(
  210. + url, origin, net::NetworkIsolationKey(), base::Time::Now(),
  211. + std::vector<uint8_t>(data.begin(), data.end()));
  212. + GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
  213. + },
  214. + context, url, origin, data, add_entry_future.GetCallback()));
  215. + ASSERT_TRUE(add_entry_future.Wait());
  216. +
  217. + // Get the code cache entry.
  218. + base::test::TestFuture<std::string> get_entry_future;
  219. + GeneratedCodeCacheContext::RunOrPostTask(
  220. + context.get(), FROM_HERE,
  221. + base::BindOnce(
  222. + [](scoped_refptr<GeneratedCodeCacheContext> context, const GURL& url,
  223. + const GURL& origin,
  224. + base::OnceCallback<void(std::string)> callback) {
  225. + context->generated_js_code_cache()->FetchEntry(
  226. + url, origin, net::NetworkIsolationKey(),
  227. + base::BindOnce(
  228. + [](base::OnceCallback<void(std::string)> callback,
  229. + const base::Time& response_time,
  230. + mojo_base::BigBuffer buffer) {
  231. + std::string data(buffer.data(),
  232. + buffer.data() + buffer.size());
  233. + GetUIThreadTaskRunner({})->PostTask(
  234. + FROM_HERE, base::BindOnce(std::move(callback), data));
  235. + },
  236. + std::move(callback)));
  237. + },
  238. + context, url, origin, get_entry_future.GetCallback()));
  239. + ASSERT_TRUE(get_entry_future.Wait());
  240. + ASSERT_EQ(data, get_entry_future.Get<0>());
  241. +}
  242. +
  243. } // namespace content
  244. diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
  245. index 15e731756530e684b583f25a3f2bdf4af3653d54..f68a97b3ebf1d2151fc19950d41b15915a334e9f 100644
  246. --- a/content/browser/renderer_host/code_cache_host_impl.cc
  247. +++ b/content/browser/renderer_host/code_cache_host_impl.cc
  248. @@ -6,6 +6,7 @@
  249. #include <utility>
  250. +#include "base/containers/contains.h"
  251. #include "base/functional/bind.h"
  252. #include "base/functional/callback_helpers.h"
  253. #include "base/metrics/histogram_functions.h"
  254. @@ -29,6 +30,7 @@
  255. #include "third_party/blink/public/common/scheme_registry.h"
  256. #include "url/gurl.h"
  257. #include "url/origin.h"
  258. +#include "url/url_util.h"
  259. using blink::mojom::CacheStorageError;
  260. @@ -36,6 +38,11 @@ namespace content {
  261. namespace {
  262. +bool ProcessLockURLIsCodeCacheScheme(const ProcessLock& process_lock) {
  263. + return base::Contains(url::GetCodeCacheSchemes(),
  264. + process_lock.lock_url().scheme());
  265. +}
  266. +
  267. bool CheckSecurityForAccessingCodeCacheData(
  268. const GURL& resource_url,
  269. int render_process_id,
  270. @@ -46,39 +53,57 @@ bool CheckSecurityForAccessingCodeCacheData(
  271. // Code caching is only allowed for http(s) and chrome/chrome-untrusted
  272. // scripts. Furthermore, there is no way for http(s) pages to load chrome or
  273. + // Code caching is only allowed for scripts from:
  274. + // 1. http: and https: schemes.
  275. + // 2. chrome: and chrome-untrusted: schemes.
  276. + // 3. Schemes registered by content/ embedder via url::AddCodeCacheScheme.
  277. + //
  278. + // Furthermore, we know there are no way for http(s) pages to load chrome or
  279. // chrome-untrusted scripts, so any http(s) page attempting to store data
  280. // about a chrome or chrome-untrusted script would be an indication of
  281. // suspicious activity.
  282. - if (resource_url.SchemeIs(content::kChromeUIScheme) ||
  283. - resource_url.SchemeIs(content::kChromeUIUntrustedScheme)) {
  284. - if (!process_lock.is_locked_to_site()) {
  285. - // We can't tell for certain whether this renderer is doing something
  286. - // malicious, but we don't trust it enough to store data.
  287. - return false;
  288. - }
  289. + if (resource_url.SchemeIsHTTPOrHTTPS()) {
  290. if (process_lock.matches_scheme(url::kHttpScheme) ||
  291. process_lock.matches_scheme(url::kHttpsScheme)) {
  292. - if (operation == CodeCacheHostImpl::Operation::kWrite) {
  293. + return true;
  294. + }
  295. + // Pages in custom schemes like isolated-app: are allowed to load http(s)
  296. + // resources.
  297. + if (ProcessLockURLIsCodeCacheScheme(process_lock)) {
  298. + return true;
  299. + }
  300. + // It is possible for WebUI pages to include open-web content, but such
  301. + // usage is rare and we've decided that reasoning about security is easier
  302. + // if the WebUI code cache includes only WebUI scripts.
  303. + return false;
  304. + }
  305. +
  306. + if (resource_url.SchemeIs(kChromeUIScheme) ||
  307. + resource_url.SchemeIs(kChromeUIUntrustedScheme)) {
  308. + if (process_lock.matches_scheme(kChromeUIScheme) ||
  309. + process_lock.matches_scheme(kChromeUIUntrustedScheme)) {
  310. + return true;
  311. + }
  312. + if (operation == CodeCacheHostImpl::Operation::kWrite) {
  313. + if (process_lock.matches_scheme(url::kHttpScheme) ||
  314. + process_lock.matches_scheme(url::kHttpsScheme)) {
  315. mojo::ReportBadMessage("HTTP(S) pages cannot cache WebUI code");
  316. }
  317. + if (ProcessLockURLIsCodeCacheScheme(process_lock)) {
  318. + mojo::ReportBadMessage(
  319. + "Page whose scheme are allowed by content/ embedders cannot cache "
  320. + "WebUI code. Did the embedder misconfigured content/?");
  321. + }
  322. return false;
  323. }
  324. // Other schemes which might successfully load chrome or chrome-untrusted
  325. // scripts, such as the PDF viewer, are unsupported but not considered
  326. - // dangerous.
  327. - return process_lock.matches_scheme(content::kChromeUIScheme) ||
  328. - process_lock.matches_scheme(content::kChromeUIUntrustedScheme);
  329. + // dangerous. Similarly, the process might not be locked to a site.
  330. + return false;
  331. }
  332. - if (resource_url.SchemeIsHTTPOrHTTPS() ||
  333. - blink::CommonSchemeRegistry::IsExtensionScheme(resource_url.scheme())) {
  334. - if (process_lock.matches_scheme(content::kChromeUIScheme) ||
  335. - process_lock.matches_scheme(content::kChromeUIUntrustedScheme)) {
  336. - // It is possible for WebUI pages to include open-web content, but such
  337. - // usage is rare and we've decided that reasoning about security is easier
  338. - // if the WebUI code cache includes only WebUI scripts.
  339. - return false;
  340. - }
  341. - return true;
  342. +
  343. + if (base::Contains(url::GetCodeCacheSchemes(), resource_url.scheme())) {
  344. + return ProcessLockURLIsCodeCacheScheme(process_lock);
  345. }
  346. if (operation == CodeCacheHostImpl::Operation::kWrite) {
  347. @@ -427,6 +452,7 @@ std::optional<GURL> CodeCacheHostImpl::GetSecondaryKeyForCodeCache(
  348. process_lock.matches_scheme(url::kHttpsScheme) ||
  349. process_lock.matches_scheme(content::kChromeUIScheme) ||
  350. process_lock.matches_scheme(content::kChromeUIUntrustedScheme) ||
  351. + ProcessLockURLIsCodeCacheScheme(process_lock) ||
  352. blink::CommonSchemeRegistry::IsExtensionScheme(
  353. process_lock.lock_url().scheme())) {
  354. return process_lock.lock_url();
  355. diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
  356. index ce9644d33fe83379127b01bf9a2b1c4badc3bc7c..fd486d4637ae4766ed78571dee7f9cebbd809f38 100644
  357. --- a/content/common/url_schemes.cc
  358. +++ b/content/common/url_schemes.cc
  359. @@ -98,6 +98,14 @@ void RegisterContentSchemes(bool should_lock_registry) {
  360. for (auto& scheme : schemes.empty_document_schemes)
  361. url::AddEmptyDocumentScheme(scheme.c_str());
  362. + for (auto& scheme : schemes.code_cache_schemes) {
  363. + CHECK_NE(scheme, kChromeUIScheme);
  364. + CHECK_NE(scheme, kChromeUIUntrustedScheme);
  365. + CHECK_NE(scheme, url::kHttpScheme);
  366. + CHECK_NE(scheme, url::kHttpsScheme);
  367. + url::AddCodeCacheScheme(scheme.c_str());
  368. + }
  369. +
  370. #if BUILDFLAG(IS_ANDROID)
  371. if (schemes.allow_non_standard_schemes_in_origins)
  372. url::EnableNonStandardSchemesForAndroidWebView();
  373. diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h
  374. index 9dc2d5a33858da7c31fd87bbbabe3899301fa52d..ebf0bb23b9aedb7bf9eb8af52b4756dba452183e 100644
  375. --- a/content/public/common/content_client.h
  376. +++ b/content/public/common/content_client.h
  377. @@ -142,6 +142,9 @@ class CONTENT_EXPORT ContentClient {
  378. // Registers a URL scheme as strictly empty documents, allowing them to
  379. // commit synchronously.
  380. std::vector<std::string> empty_document_schemes;
  381. + // Registers a URL scheme whose js and wasm scripts have V8 code cache
  382. + // enabled.
  383. + std::vector<std::string> code_cache_schemes;
  384. // Registers a URL scheme as extension scheme.
  385. std::vector<std::string> extension_schemes;
  386. // Registers a URL scheme with a predefined default custom handler.
  387. diff --git a/url/url_util.cc b/url/url_util.cc
  388. index ce5225e121f5db611d95ba5dfa88cea42f32076b..d402cc9db212abcedd62018bb242eb524cc6acf2 100644
  389. --- a/url/url_util.cc
  390. +++ b/url/url_util.cc
  391. @@ -135,6 +135,9 @@ struct SchemeRegistry {
  392. kMaterializedViewScheme,
  393. };
  394. + // Embedder schemes that have V8 code cache enabled in js and wasm scripts.
  395. + std::vector<std::string> code_cache_schemes = {};
  396. +
  397. // Schemes with a predefined default custom handler.
  398. std::vector<SchemeWithHandler> predefined_handler_schemes;
  399. @@ -716,6 +719,15 @@ const std::vector<std::string>& GetEmptyDocumentSchemes() {
  400. return GetSchemeRegistry().empty_document_schemes;
  401. }
  402. +void AddCodeCacheScheme(const char* new_scheme) {
  403. + DoAddScheme(new_scheme,
  404. + &GetSchemeRegistryWithoutLocking()->code_cache_schemes);
  405. +}
  406. +
  407. +const std::vector<std::string>& GetCodeCacheSchemes() {
  408. + return GetSchemeRegistry().code_cache_schemes;
  409. +}
  410. +
  411. void AddPredefinedHandlerScheme(const char* new_scheme, const char* handler) {
  412. DoAddSchemeWithHandler(
  413. new_scheme, handler,
  414. diff --git a/url/url_util.h b/url/url_util.h
  415. index e39a44057cebce7cdf90bcb02a7463e88bd271b4..e80b81d2ddeb2ec201b143d86bec6ee54ca49afc 100644
  416. --- a/url/url_util.h
  417. +++ b/url/url_util.h
  418. @@ -115,6 +115,15 @@ COMPONENT_EXPORT(URL) const std::vector<std::string>& GetCSPBypassingSchemes();
  419. COMPONENT_EXPORT(URL) void AddEmptyDocumentScheme(const char* new_scheme);
  420. COMPONENT_EXPORT(URL) const std::vector<std::string>& GetEmptyDocumentSchemes();
  421. +// Adds an application-defined scheme to the list of schemes that have V8 code
  422. +// cache enabled for the js and wasm scripts.
  423. +// The WebUI schemes (chrome/chrome-untrusted) do not belong to this list, as
  424. +// they are treated as a separate cache type for security purpose.
  425. +// The http(s) schemes do not belong to this list neither, they always have V8
  426. +// code cache enabled.
  427. +COMPONENT_EXPORT(URL) void AddCodeCacheScheme(const char* new_scheme);
  428. +COMPONENT_EXPORT(URL) const std::vector<std::string>& GetCodeCacheSchemes();
  429. +
  430. // Adds a scheme with a predefined default handler.
  431. //
  432. // This pair of strings must be normalized protocol handler parameters as