delay_lock_the_protocol_scheme_registry.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Andy Locascio <[email protected]>
  3. Date: Tue, 18 Feb 2020 14:35:04 -0800
  4. Subject: content: allow embedder to prevent locking scheme registry
  5. The //content layer requires all schemes to be registered during startup,
  6. because Add*Scheme aren't threadsafe. However, Electron exposes the option to
  7. register additional schemes via JavaScript in the main process before the app
  8. is ready, but after the //content layer has already locked the registry.
  9. This allows embedders to optionally keep the scheme registry unlocked, and it
  10. is their responsibility to ensure that it is not accessed in a way that would
  11. cause potential thread-safety issues.
  12. Previously upstreamed patch: https://chromium-review.googlesource.com/c/chromium/src/+/1637040
  13. This change was lost during upstream refactor in
  14. https://chromium-review.googlesource.com/c/chromium/src/+/1901591, we should try
  15. re-submitting the patch.
  16. diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
  17. index 12055944205a9d8de54e6d3ff66e99b723fa5752..b46a9f4ad5f07c2a8e649edbfb52b52f9f6e9946 100644
  18. --- a/content/app/content_main_runner_impl.cc
  19. +++ b/content/app/content_main_runner_impl.cc
  20. @@ -663,7 +663,7 @@ int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
  21. }
  22. #endif
  23. - RegisterContentSchemes();
  24. + RegisterContentSchemes(delegate_->ShouldLockSchemeRegistry());
  25. ContentClientInitializer::Set(process_type, delegate_);
  26. #if !defined(OS_ANDROID)
  27. diff --git a/content/common/url_schemes.cc b/content/common/url_schemes.cc
  28. index dc37f121130d83e200d73dd1ad566847548ac0fd..63080c1bc486a488841fc5d2081f4d5d4a00bde3 100644
  29. --- a/content/common/url_schemes.cc
  30. +++ b/content/common/url_schemes.cc
  31. @@ -49,7 +49,7 @@ std::vector<std::string>& GetMutableServiceWorkerSchemes() {
  32. } // namespace
  33. -void RegisterContentSchemes() {
  34. +void RegisterContentSchemes(bool should_lock_registry) {
  35. // On Android and in tests, schemes may have been registered already.
  36. if (g_registered_url_schemes)
  37. return;
  38. @@ -106,7 +106,8 @@ void RegisterContentSchemes() {
  39. // threadsafe so must be called when GURL isn't used on any other thread. This
  40. // is really easy to mess up, so we say that all calls to Add*Scheme in Chrome
  41. // must be inside this function.
  42. - url::LockSchemeRegistries();
  43. + if (should_lock_registry)
  44. + url::LockSchemeRegistries();
  45. // Combine the default savable schemes with the additional ones given.
  46. GetMutableSavableSchemes().assign(std::begin(kDefaultSavableSchemes),
  47. diff --git a/content/common/url_schemes.h b/content/common/url_schemes.h
  48. index 3038f9d25798f36811b6398f8cc0e7d83ecc41b0..68189c36c47ef85b345b0ccc40c456f889977bee 100644
  49. --- a/content/common/url_schemes.h
  50. +++ b/content/common/url_schemes.h
  51. @@ -16,7 +16,7 @@ namespace content {
  52. // parsed as "standard" or "referrer" with the src/url/ library, then locks the
  53. // sets of schemes down. The embedder can add additional schemes by
  54. // overriding the ContentClient::AddAdditionalSchemes method.
  55. -CONTENT_EXPORT void RegisterContentSchemes();
  56. +CONTENT_EXPORT void RegisterContentSchemes(bool should_lock_registry = true);
  57. // Re-initializes schemes for tests.
  58. CONTENT_EXPORT void ReRegisterContentSchemesForTests();
  59. diff --git a/content/public/app/content_main_delegate.cc b/content/public/app/content_main_delegate.cc
  60. index ed5b0e2c0b4d453560ee9e2e4a55780b409eeea9..46e29dca5d13691bcf9494c0f90b68d6219a75ef 100644
  61. --- a/content/public/app/content_main_delegate.cc
  62. +++ b/content/public/app/content_main_delegate.cc
  63. @@ -37,6 +37,10 @@ int ContentMainDelegate::TerminateForFatalInitializationError() {
  64. return 0;
  65. }
  66. +bool ContentMainDelegate::ShouldLockSchemeRegistry() {
  67. + return true;
  68. +}
  69. +
  70. service_manager::ProcessType ContentMainDelegate::OverrideProcessType() {
  71. return service_manager::ProcessType::kDefault;
  72. }
  73. diff --git a/content/public/app/content_main_delegate.h b/content/public/app/content_main_delegate.h
  74. index 2d9ee9fa20a9aba1de168cc86bfeea5eab71e6d3..4b163c3fa2ddd258b5527e0ccaf9fc9d2621ef75 100644
  75. --- a/content/public/app/content_main_delegate.h
  76. +++ b/content/public/app/content_main_delegate.h
  77. @@ -77,6 +77,20 @@ class CONTENT_EXPORT ContentMainDelegate {
  78. // returning initialization error code. Default behavior is CHECK(false).
  79. virtual int TerminateForFatalInitializationError();
  80. + // Allows the embedder to prevent locking the scheme registry. The scheme
  81. + // registry is the list of URL schemes we recognize, with some additional
  82. + // information about each scheme such as whether it expects a host. The
  83. + // scheme registry is not thread-safe, so by default it is locked before any
  84. + // threads are created to ensure single-threaded access. An embedder can
  85. + // override this to prevent the scheme registry from being locked during
  86. + // startup, but if they do so then they are responsible for making sure that
  87. + // the registry is only accessed in a thread-safe way, and for calling
  88. + // url::LockSchemeRegistries() when initialization is complete. If possible,
  89. + // prefer registering additional schemes through
  90. + // ContentClient::AddAdditionalSchemes over preventing the scheme registry
  91. + // from being locked.
  92. + virtual bool ShouldLockSchemeRegistry();
  93. +
  94. // Overrides the Service Manager process type to use for the currently running
  95. // process.
  96. virtual service_manager::ProcessType OverrideProcessType();