• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/base/base_paths_ohos.cc b/base/base_paths_ohos.cc
2index ec03cd53d7..fb6e3966f6 100644
3--- a/base/base_paths_ohos.cc
4+++ b/base/base_paths_ohos.cc
5@@ -15,6 +15,11 @@
6 #include "base/notreached.h"
7 #include "base/process/process_metrics.h"
8
9+#if defined(OS_OHOS)
10+#include "base/command_line.h"
11+#include "content/public/common/content_switches.h"
12+#endif
13+
14 namespace base {
15
16 bool PathProviderOHOS(int key, FilePath* result) {
17@@ -49,10 +54,20 @@ bool PathProviderOHOS(int key, FilePath* result) {
18       // set to /data/local directory for W|X permission.
19       *result = FilePath("/data/local");
20       return true;
21-    case base::DIR_ASSETS:
22+    case base::DIR_ASSETS: {
23       // resource file packed to system images
24-      *result = FilePath("/system/etc/webview");
25+#if defined(OS_OHOS)
26+      bool for_test = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForTest);
27+      if (for_test) {
28+        *result = FilePath("/data/app/el1/bundle/public/com.ohos.nweb/entry/resources/rawfile");
29+      } else {
30+        *result = FilePath("/data/storage/el1/bundle/nweb/entry/resources/rawfile");
31+      }
32+#else
33+        *result = FilePath("/data/local");
34+#endif
35       return true;
36+    }
37     case base::DIR_OHOS_APP_DATA:
38       *result = FilePath("/data/local");
39       return true;
40diff --git a/build/config/ohos/BUILD.gn b/build/config/ohos/BUILD.gn
41index 534f0020d7..881d941065 100644
42--- a/build/config/ohos/BUILD.gn
43+++ b/build/config/ohos/BUILD.gn
44@@ -131,12 +131,12 @@ config("runtime_library") {
45   }
46   if (use_musl) {
47     ldflags += [
48-      "-L" + rebase_path("$ohos_sysroot/usr/lib/arm-linux-ohosmusl", root_build_dir),
49-      "-L" + rebase_path("$ohos_toolchain_root/lib/arm-linux-ohosmusl/c++", root_build_dir),
50-      "-L" + rebase_path("$ohos_toolchain_root/lib/clang/10.0.1/lib/arm-linux-ohosmusl", root_build_dir),
51+      "-L" + rebase_path("$ohos_sysroot/usr/lib/arm-linux-ohos", root_build_dir),
52+      "-L" + rebase_path("$ohos_toolchain_root/lib/arm-linux-ohos/c++", root_build_dir),
53+      "-L" + rebase_path("$ohos_toolchain_root/lib/clang/10.0.1/lib/arm-linux-ohos", root_build_dir),
54     ]
55-    ldflags += [ "-Wl,--dynamic-linker,/system/bin/ld-musl-arm.so.1" ]
56-    libclang_rt_file = "$ohos_toolchain_root/lib/clang/10.0.1/lib/arm-linux-ohosmusl/libclang_rt.builtins.a"
57+    ldflags += [ "-Wl,--dynamic-linker,/lib/ld-musl-arm.so.1" ]
58+    libclang_rt_file = "$ohos_toolchain_root/lib/clang/10.0.1/lib/arm-linux-ohos/libclang_rt.builtins.a"
59
60     libs += [
61       rebase_path(libclang_rt_file),
62diff --git a/build/config/ohos/config.gni b/build/config/ohos/config.gni
63index c2d04f6262..6a2442e261 100644
64--- a/build/config/ohos/config.gni
65+++ b/build/config/ohos/config.gni
66@@ -13,7 +13,11 @@ if (is_ohos) {
67   }
68
69   declare_args() {
70-    build_chromium_with_ohos_src = false
71+    build_chromium_with_ohos_src = true
72+  }
73+
74+  declare_args() {
75+    product_name = ""
76   }
77
78   # Defines the name the ohos build gives to the current host CPU
79@@ -42,7 +46,7 @@ if (is_ohos) {
80     ohos_build_root = "//../../.."
81     if (use_musl) {
82       ohos_toolchain_root = "$ohos_ndk_root/clang/ohos/linux-x86_64/llvm"
83-      ohos_sysroot = "$ohos_build_root/out/ohos-arm-release/obj/third_party/musl"
84+      ohos_sysroot = "$ohos_build_root/out/rk3568/obj/third_party/musl"
85     } else {
86       ohos_toolchain_root = "$ohos_ndk_root/clang/host/linux-x86/clang-r353983c"
87       ohos_sysroot = "$ohos_ndk_root/aosp_prebuilt_libs/asdk_libs/ndk/platforms/current/arch-arm"
88@@ -70,9 +74,19 @@ if (is_ohos) {
89       "$ohos_build_root/base/location/interfaces/innerkits/locator_standard/include",
90       "$ohos_build_root/base/location/location_common/common/include",
91       "$ohos_build_root/foundation/distributedschedule/samgr/interfaces/innerkits/samgr_proxy/include",
92+      "$ohos_build_root/utils/system/safwk/native/include",
93+      "$ohos_build_root/foundation/aafwk/standard/interfaces/innerkits/base/include",
94+      "$ohos_build_root/foundation/aafwk/standard/interfaces/innerkits/want/include/ohos/aafwk/content",
95+      "$ohos_build_root/foundation/appexecfwk/standard/common/log/include",
96+      "$ohos_build_root/foundation/appexecfwk/standard/common/perf/include",
97+      "$ohos_build_root/foundation/appexecfwk/standard/interfaces/innerkits/appexecfwk_base/include",
98+      "$ohos_build_root/foundation/aafwk/standard/interfaces/innerkits/app_manager/include",
99+      "$ohos_build_root/foundation/distributedschedule/dmsfwk/services/dtbschedmgr/include",
100+      "$ohos_build_root/third_party/jsoncpp/include",
101+      "$ohos_build_root/third_party/json/include"
102     ]
103     ohos_libs_dir = [
104-      "$ohos_build_root/out/ohos-arm-release/packages/phone/system/lib",
105+      "$ohos_build_root/out/rk3568/packages/phone/system/lib",
106     ]
107   } else {
108     if (use_musl) {
109diff --git a/cef/libcef/browser/native/menu_runner_linux.cc b/cef/libcef/browser/native/menu_runner_linux.cc
110index 220d06c302..951deef09f 100644
111--- a/cef/libcef/browser/native/menu_runner_linux.cc
112+++ b/cef/libcef/browser/native/menu_runner_linux.cc
113@@ -7,6 +7,7 @@
114 #include "libcef/browser/alloy/alloy_browser_host_impl.h"
115
116 #include "base/compiler_specific.h"
117+#include "base/logging.h"
118 #include "base/strings/string_util.h"
119 #include "ui/gfx/geometry/point.h"
120
121@@ -16,6 +17,7 @@ bool CefMenuRunnerLinux::RunContextMenu(
122     AlloyBrowserHostImpl* browser,
123     CefMenuModelImpl* model,
124     const content::ContextMenuParams& params) {
125+#if !defined(OS_OHOS) // will implement for ohos later
126   menu_.reset(
127       new views::MenuRunner(model->model(), views::MenuRunner::CONTEXT_MENU));
128
129@@ -28,13 +30,18 @@ bool CefMenuRunnerLinux::RunContextMenu(
130
131   menu_->RunMenuAt(parent_widget, nullptr, gfx::Rect(screen_point, gfx::Size()),
132                    views::MenuAnchorPosition::kTopRight, ui::MENU_SOURCE_NONE);
133+#else
134+  LOG(INFO) << "context menu not implement for ohos yet!";
135+#endif
136
137   return true;
138 }
139
140 void CefMenuRunnerLinux::CancelContextMenu() {
141+#if !defined(OS_OHOS) // will implement for ohos later
142   if (menu_)
143     menu_->Cancel();
144+#endif
145 }
146
147 bool CefMenuRunnerLinux::FormatLabel(std::u16string& label) {
148diff --git a/cef/libcef/browser/native/menu_runner_linux.h b/cef/libcef/browser/native/menu_runner_linux.h
149index 503461370d..89bb3f51b1 100644
150--- a/cef/libcef/browser/native/menu_runner_linux.h
151+++ b/cef/libcef/browser/native/menu_runner_linux.h
152@@ -22,7 +22,9 @@ class CefMenuRunnerLinux : public CefMenuRunner {
153   bool FormatLabel(std::u16string& label) override;
154
155  private:
156+#if !defined(OS_OHOS) // will implement for ohos later
157   std::unique_ptr<views::MenuRunner> menu_;
158+#endif
159 };
160
161 #endif  // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
162diff --git a/cef/libcef/browser/net_service/cookie_helper.cc b/cef/libcef/browser/net_service/cookie_helper.cc
163index 6b2adf40cc..0f0af971f7 100644
164--- a/cef/libcef/browser/net_service/cookie_helper.cc
165+++ b/cef/libcef/browser/net_service/cookie_helper.cc
166@@ -192,7 +192,7 @@ void LoadCookies(content::BrowserContext* browser_context,
167
168   if ((request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) ||
169       request.credentials_mode == network::mojom::CredentialsMode::kOmit ||
170-      request.url.IsAboutBlank()) {
171+      request.url.IsAboutBlank() || !request.SendsCookies()) {
172     // Continue immediately without loading cookies.
173     std::move(done_callback).Run(0, {});
174     return;
175@@ -213,7 +213,8 @@ void SaveCookies(content::BrowserContext* browser_context,
176
177   if (request.credentials_mode == network::mojom::CredentialsMode::kOmit ||
178       request.url.IsAboutBlank() || !headers ||
179-      !headers->HasHeader(net_service::kHTTPSetCookieHeaderName)) {
180+      !headers->HasHeader(net_service::kHTTPSetCookieHeaderName) ||
181+      !request.SavesCookies()) {
182     // Continue immediately without saving cookies.
183     std::move(done_callback).Run(0, {});
184     return;
185diff --git a/cef/libcef/browser/osr/render_widget_host_view_osr.cc b/cef/libcef/browser/osr/render_widget_host_view_osr.cc
186index b8ccb16d4f..f52387c298 100644
187--- a/cef/libcef/browser/osr/render_widget_host_view_osr.cc
188+++ b/cef/libcef/browser/osr/render_widget_host_view_osr.cc
189@@ -972,6 +972,7 @@ void CefRenderWidgetHostViewOSR::WasResized() {
190
191   SynchronizeVisualProperties(cc::DeadlinePolicy::UseExistingDeadline(),
192                               base::nullopt);
193+  ReleaseResizeHold();
194 }
195
196 void CefRenderWidgetHostViewOSR::SynchronizeVisualProperties(
197diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
198index 23317546e6..d6236627e3 100644
199--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
200+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
201@@ -324,6 +324,7 @@ void BackgroundFetchDelegateImpl::DownloadUrl(
202     const std::string& download_guid,
203     const std::string& method,
204     const GURL& url,
205+    ::network::mojom::CredentialsMode credentials_mode,
206     const net::NetworkTrafficAnnotationTag& traffic_annotation,
207     const net::HttpRequestHeaders& headers,
208     bool has_request_body) {
209@@ -339,6 +340,7 @@ void BackgroundFetchDelegateImpl::DownloadUrl(
210   params.request_params.method = method;
211   params.request_params.url = url;
212   params.request_params.request_headers = headers;
213+  params.request_params.credentials_mode = credentials_mode;
214   params.callback =
215       base::BindRepeating(&BackgroundFetchDelegateImpl::OnDownloadReceived,
216                           weak_ptr_factory_.GetWeakPtr());
217diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
218index 16629fb82d..dfffa83b42 100644
219--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h
220+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
221@@ -97,6 +97,7 @@ class BackgroundFetchDelegateImpl
222                    const std::string& guid,
223                    const std::string& method,
224                    const GURL& url,
225+                   ::network::mojom::CredentialsMode credentials_mode,
226                    const net::NetworkTrafficAnnotationTag& traffic_annotation,
227                    const net::HttpRequestHeaders& headers,
228                    bool has_request_body) override;
229diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
230index 005625bb1c..127f6fb2c9 100644
231--- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
232+++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
233@@ -205,11 +205,9 @@ void ChromeContentBrowserClient::ExposeInterfacesToRenderer(
234       ui_task_runner);
235 #endif
236 #if defined(OS_ANDROID)
237-  Profile* profile =
238-      Profile::FromBrowserContext(render_process_host->GetBrowserContext());
239   registry->AddInterface(
240       base::BindRepeating(&android::AvailableOfflineContentProvider::Create,
241-                          profile),
242+                          render_process_host->GetID()),
243       content::GetUIThreadTaskRunner({}));
244 #endif
245
246diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
247index fd8ec071c4..2ffc8f4b29 100644
248--- a/chrome/browser/chrome_security_exploit_browsertest.cc
249+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
250@@ -482,8 +482,8 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
251
252   // If the process is killed, this test passes.
253   EXPECT_EQ(
254-      "Received bad user message: Non committable URL passed to "
255-      "BlobURLStore::Register",
256+      "Received bad user message: "
257+      "URL with invalid origin passed to BlobURLStore::Register",
258       crash_observer.Wait());
259 }
260
261@@ -518,7 +518,7 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
262
263   // If the process is killed, this test passes.
264   EXPECT_EQ(
265-      "Received bad user message: Non committable URL passed to "
266-      "BlobURLStore::Register",
267+      "Received bad user message: "
268+      "URL with invalid origin passed to BlobURLStore::Register",
269       crash_observer.Wait());
270 }
271diff --git a/chrome/browser/download/android/available_offline_content_provider.cc b/chrome/browser/download/android/available_offline_content_provider.cc
272index 355efc81c2..680d00ee6f 100644
273--- a/chrome/browser/download/android/available_offline_content_provider.cc
274+++ b/chrome/browser/download/android/available_offline_content_provider.cc
275@@ -25,6 +25,7 @@
276 #include "components/offline_items_collection/core/offline_item_state.h"
277 #include "components/offline_pages/core/offline_page_feature.h"
278 #include "components/prefs/pref_service.h"
279+#include "content/public/browser/render_process_host.h"
280 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
281 #include "ui/base/l10n/time_format.h"
282
283@@ -217,14 +218,17 @@ chrome::mojom::AvailableOfflineContentPtr CreateAvailableOfflineContent(
284 }  // namespace
285
286 AvailableOfflineContentProvider::AvailableOfflineContentProvider(
287-    Profile* profile)
288-    : profile_(profile) {}
289+    int render_process_host_id)
290+    : render_process_host_id_(render_process_host_id) {}
291
292 AvailableOfflineContentProvider::~AvailableOfflineContentProvider() = default;
293
294 void AvailableOfflineContentProvider::List(ListCallback callback) {
295+  Profile* profile = GetProfile();
296+  if (!profile)
297+    return;
298   offline_items_collection::OfflineContentAggregator* aggregator =
299-      OfflineContentAggregatorFactory::GetForKey(profile_->GetProfileKey());
300+      OfflineContentAggregatorFactory::GetForKey(profile->GetProfileKey());
301   aggregator->GetAllItems(
302       base::BindOnce(&AvailableOfflineContentProvider::ListFinalize,
303                      weak_ptr_factory_.GetWeakPtr(), std::move(callback),
304@@ -236,12 +240,15 @@ void AvailableOfflineContentProvider::List(ListCallback callback) {
305 void AvailableOfflineContentProvider::LaunchItem(
306     const std::string& item_id,
307     const std::string& name_space) {
308+  Profile* profile = GetProfile();
309+  if (!profile)
310+    return;
311   offline_items_collection::OfflineContentAggregator* aggregator =
312-      OfflineContentAggregatorFactory::GetForKey(profile_->GetProfileKey());
313+      OfflineContentAggregatorFactory::GetForKey(profile->GetProfileKey());
314
315   offline_items_collection::OpenParams open_params(
316       offline_items_collection::LaunchLocation::NET_ERROR_SUGGESTION);
317-  open_params.open_in_incognito = profile_->IsOffTheRecord();
318+  open_params.open_in_incognito = profile->IsOffTheRecord();
319   aggregator->OpenItem(
320       open_params, offline_items_collection::ContentId(name_space, item_id));
321 }
322@@ -254,20 +261,21 @@ void AvailableOfflineContentProvider::LaunchDownloadsPage(
323 }
324
325 void AvailableOfflineContentProvider::ListVisibilityChanged(bool is_visible) {
326-  profile_->GetPrefs()->SetBoolean(feed::prefs::kArticlesListVisible,
327-                                   is_visible);
328+  Profile* profile = GetProfile();
329+  if (!profile)
330+    return;
331+  profile->GetPrefs()->SetBoolean(feed::prefs::kArticlesListVisible,
332+                                  is_visible);
333 }
334
335 // static
336 void AvailableOfflineContentProvider::Create(
337-    Profile* profile,
338+    int render_process_host_id,
339     mojo::PendingReceiver<chrome::mojom::AvailableOfflineContentProvider>
340         receiver) {
341-  // Self owned receiveres remain as long as the pipe is error free. The
342-  // renderer is on the other side of the pipe, and the profile outlives the
343-  // RenderProcessHost, so the profile will outlive the Mojo pipe.
344+  // Self owned receiveres remain as long as the pipe is error free.
345   mojo::MakeSelfOwnedReceiver(
346-      std::make_unique<AvailableOfflineContentProvider>(profile),
347+      std::make_unique<AvailableOfflineContentProvider>(render_process_host_id),
348       std::move(receiver));
349 }
350
351@@ -276,6 +284,10 @@ void AvailableOfflineContentProvider::ListFinalize(
352     AvailableOfflineContentProvider::ListCallback callback,
353     offline_items_collection::OfflineContentAggregator* aggregator,
354     const std::vector<OfflineItem>& all_items) {
355+  Profile* profile = GetProfile();
356+  if (!profile)
357+    return;
358+
359   std::vector<OfflineItem> selected(kMinInterestingItemCount);
360   const auto end = std::partial_sort_copy(all_items.begin(), all_items.end(),
361                                           selected.begin(), selected.end(),
362@@ -296,7 +308,7 @@ void AvailableOfflineContentProvider::ListFinalize(
363     selected_ids.push_back(item.id);
364
365   bool list_visible_by_prefs =
366-      profile_->GetPrefs()->GetBoolean(feed::prefs::kArticlesListVisible);
367+      profile->GetPrefs()->GetBoolean(feed::prefs::kArticlesListVisible);
368
369   auto complete =
370       [](AvailableOfflineContentProvider::ListCallback callback,
371@@ -318,4 +330,12 @@ void AvailableOfflineContentProvider::ListFinalize(
372                      list_visible_by_prefs));
373 }
374
375+Profile* AvailableOfflineContentProvider::GetProfile() {
376+  content::RenderProcessHost* render_process_host =
377+      content::RenderProcessHost::FromID(render_process_host_id_);
378+  if (!render_process_host)
379+    return nullptr;
380+  return Profile::FromBrowserContext(render_process_host->GetBrowserContext());
381+}
382+
383 }  // namespace android
384diff --git a/chrome/browser/download/android/available_offline_content_provider.h b/chrome/browser/download/android/available_offline_content_provider.h
385index c4024a463a..0888c0c487 100644
386--- a/chrome/browser/download/android/available_offline_content_provider.h
387+++ b/chrome/browser/download/android/available_offline_content_provider.h
388@@ -27,7 +27,7 @@ class AvailableOfflineContentProvider
389     : public chrome::mojom::AvailableOfflineContentProvider {
390  public:
391   // Public for testing.
392-  explicit AvailableOfflineContentProvider(Profile* profile);
393+  explicit AvailableOfflineContentProvider(int render_process_host_id);
394   ~AvailableOfflineContentProvider() override;
395
396   // chrome::mojom::AvailableOfflineContentProvider methods.
397@@ -38,7 +38,7 @@ class AvailableOfflineContentProvider
398   void ListVisibilityChanged(bool is_visible) override;
399
400   static void Create(
401-      Profile* profile,
402+      int render_process_host_id,
403       mojo::PendingReceiver<chrome::mojom::AvailableOfflineContentProvider>
404           receiver);
405
406@@ -48,7 +48,9 @@ class AvailableOfflineContentProvider
407       offline_items_collection::OfflineContentAggregator* aggregator,
408       const std::vector<offline_items_collection::OfflineItem>& all_items);
409
410-  Profile* profile_;
411+  Profile* GetProfile();
412+
413+  const int render_process_host_id_;
414
415   base::WeakPtrFactory<AvailableOfflineContentProvider> weak_ptr_factory_{this};
416
417diff --git a/chrome/browser/download/android/available_offline_content_provider_unittest.cc b/chrome/browser/download/android/available_offline_content_provider_unittest.cc
418index 234760aff0..bce18ff21b 100644
419--- a/chrome/browser/download/android/available_offline_content_provider_unittest.cc
420+++ b/chrome/browser/download/android/available_offline_content_provider_unittest.cc
421@@ -15,6 +15,7 @@
422 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
423 #include "chrome/browser/profiles/profile_key.h"
424 #include "chrome/common/available_offline_content.mojom-test-utils.h"
425+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
426 #include "chrome/test/base/testing_profile.h"
427 #include "components/feed/core/shared_prefs/pref_names.h"
428 #include "components/offline_items_collection/core/offline_content_aggregator.h"
429@@ -124,13 +125,27 @@ OfflineItemVisuals TestThumbnail() {
430   return visuals;
431 }
432
433-class AvailableOfflineContentTest : public testing::Test {
434+class AvailableOfflineContentTest : public ChromeRenderViewHostTestHarness {
435  protected:
436   void SetUp() override {
437+    ChromeRenderViewHostTestHarness::SetUp();
438+
439+    content_provider_ = std::make_unique<
440+        offline_items_collection::MockOfflineContentProvider>();
441+    provider_ = std::make_unique<AvailableOfflineContentProvider>(
442+        main_rfh()->GetProcess()->GetID());
443+
444     aggregator_ =
445-        OfflineContentAggregatorFactory::GetForKey(profile_.GetProfileKey());
446-    aggregator_->RegisterProvider(kProviderNamespace, &content_provider_);
447-    content_provider_.SetVisuals({});
448+        OfflineContentAggregatorFactory::GetForKey(profile()->GetProfileKey());
449+    aggregator_->RegisterProvider(kProviderNamespace, content_provider_.get());
450+    content_provider_->SetVisuals({});
451+  }
452+
453+  void TearDown() override {
454+    provider_.release();
455+    content_provider_.release();
456+
457+    ChromeRenderViewHostTestHarness::TearDown();
458   }
459
460   std::tuple<bool, std::vector<chrome::mojom::AvailableOfflineContentPtr>>
461@@ -138,18 +153,17 @@ class AvailableOfflineContentTest : public testing::Test {
462     bool list_visible_by_prefs;
463     std::vector<chrome::mojom::AvailableOfflineContentPtr> suggestions;
464     chrome::mojom::AvailableOfflineContentProviderAsyncWaiter waiter(
465-        &provider_);
466+        provider_.get());
467     waiter.List(&list_visible_by_prefs, &suggestions);
468     return std::make_tuple(list_visible_by_prefs, std::move(suggestions));
469   }
470
471-  content::BrowserTaskEnvironment task_environment_;
472-  TestingProfile profile_;
473   std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_ =
474       std::make_unique<base::test::ScopedFeatureList>();
475   OfflineContentAggregator* aggregator_;
476-  offline_items_collection::MockOfflineContentProvider content_provider_;
477-  AvailableOfflineContentProvider provider_{&profile_};
478+  std::unique_ptr<offline_items_collection::MockOfflineContentProvider>
479+      content_provider_;
480+  std::unique_ptr<AvailableOfflineContentProvider> provider_;
481 };
482
483 TEST_F(AvailableOfflineContentTest, NoContent) {
484@@ -164,10 +178,10 @@ TEST_F(AvailableOfflineContentTest, NoContent) {
485 TEST_F(AvailableOfflineContentTest, TooFewInterestingItems) {
486   // Adds items so that we're one-ff of reaching the minimum required count so
487   // that any extra item considered interesting would effect the results.
488-  content_provider_.SetItems({UninterestingImageItem(), OfflinePageItem(),
489-                              SuggestedOfflinePageItem(), VideoItem(),
490-                              TransientItem(), OffTheRecordItem(),
491-                              IncompleteItem(), DangerousItem()});
492+  content_provider_->SetItems({UninterestingImageItem(), OfflinePageItem(),
493+                               SuggestedOfflinePageItem(), VideoItem(),
494+                               TransientItem(), OffTheRecordItem(),
495+                               IncompleteItem(), DangerousItem()});
496
497   // Call List().
498   bool list_visible_by_prefs;
499@@ -182,11 +196,11 @@ TEST_F(AvailableOfflineContentTest, TooFewInterestingItems) {
500
501 TEST_F(AvailableOfflineContentTest, FourInterestingItems) {
502   // We need at least 4 interesting items for anything to show up at all.
503-  content_provider_.SetItems({UninterestingImageItem(), VideoItem(),
504-                              SuggestedOfflinePageItem(), AudioItem(),
505-                              OfflinePageItem()});
506+  content_provider_->SetItems({UninterestingImageItem(), VideoItem(),
507+                               SuggestedOfflinePageItem(), AudioItem(),
508+                               OfflinePageItem()});
509
510-  content_provider_.SetVisuals(
511+  content_provider_->SetVisuals(
512       {{SuggestedOfflinePageItem().id, TestThumbnail()}});
513
514   // Call List().
515@@ -226,14 +240,14 @@ TEST_F(AvailableOfflineContentTest, FourInterestingItems) {
516
517 TEST_F(AvailableOfflineContentTest, ListVisibilityChanges) {
518   // We need at least 4 interesting items for anything to show up at all.
519-  content_provider_.SetItems({UninterestingImageItem(), VideoItem(),
520-                              SuggestedOfflinePageItem(), AudioItem(),
521-                              OfflinePageItem()});
522+  content_provider_->SetItems({UninterestingImageItem(), VideoItem(),
523+                               SuggestedOfflinePageItem(), AudioItem(),
524+                               OfflinePageItem()});
525
526-  content_provider_.SetVisuals(
527+  content_provider_->SetVisuals(
528       {{SuggestedOfflinePageItem().id, TestThumbnail()}});
529   // Set pref to hide the list.
530-  profile_.GetPrefs()->SetBoolean(feed::prefs::kArticlesListVisible, false);
531+  profile()->GetPrefs()->SetBoolean(feed::prefs::kArticlesListVisible, false);
532
533   // Call List().
534   bool list_visible_by_prefs;
535@@ -245,10 +259,10 @@ TEST_F(AvailableOfflineContentTest, ListVisibilityChanges) {
536   EXPECT_FALSE(list_visible_by_prefs);
537
538   // Simulate visibility changed by the user to "shown".
539-  provider_.ListVisibilityChanged(true);
540+  provider_->ListVisibilityChanged(true);
541
542   EXPECT_TRUE(
543-      profile_.GetPrefs()->GetBoolean(feed::prefs::kArticlesListVisible));
544+      profile()->GetPrefs()->GetBoolean(feed::prefs::kArticlesListVisible));
545
546   // Call List() again and check list is not visible.
547   std::tie(list_visible_by_prefs, suggestions) = ListAndWait();
548diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
549index b5e3997002..ef21c3d4fc 100644
550--- a/chrome/browser/download/save_page_browsertest.cc
551+++ b/chrome/browser/download/save_page_browsertest.cc
552@@ -49,6 +49,7 @@
553 #include "components/prefs/pref_member.h"
554 #include "components/prefs/pref_service.h"
555 #include "components/security_state/core/security_state.h"
556+#include "components/services/quarantine/test_support.h"
557 #include "content/public/browser/download_manager.h"
558 #include "content/public/browser/notification_service.h"
559 #include "content/public/browser/notification_types.h"
560@@ -433,6 +434,10 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveFileURL) {
561   EXPECT_TRUE(base::PathExists(full_file_name));
562   EXPECT_FALSE(base::PathExists(dir));
563   EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
564+#if defined(OS_WIN)
565+  // Local file URL will not be quarantined.
566+  EXPECT_FALSE(quarantine::IsFileQuarantined(full_file_name, GURL(), GURL()));
567+#endif
568 }
569
570 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
571@@ -936,6 +941,25 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveUnauthorizedResource) {
572   EXPECT_FALSE(base::PathExists(dir.AppendASCII("should-not-save.jpg")));
573 }
574
575+#if defined(OS_WIN)
576+// Save a file and confirm that the file is correctly quarantined.
577+IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveURLQuarantine) {
578+  GURL url = embedded_test_server()->GetURL("/save_page/text.txt");
579+  ui_test_utils::NavigateToURL(browser(), url);
580+
581+  base::FilePath full_file_name, dir;
582+  SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_ONLY_HTML, "test", 1, &dir,
583+                 &full_file_name);
584+  ASSERT_FALSE(HasFailure());
585+
586+  base::ScopedAllowBlockingForTesting allow_blocking;
587+  EXPECT_TRUE(base::PathExists(full_file_name));
588+  EXPECT_FALSE(base::PathExists(dir));
589+  EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
590+  EXPECT_TRUE(quarantine::IsFileQuarantined(full_file_name, url, GURL()));
591+}
592+#endif
593+
594 // Test suite that allows testing --site-per-process against cross-site frames.
595 // See http://dev.chromium.org/developers/design-documents/site-isolation.
596 class SavePageSitePerProcessBrowserTest : public SavePageBrowserTest {
597diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
598index 4caf88b061..496ae84131 100644
599--- a/chrome/browser/extensions/extension_messages_apitest.cc
600+++ b/chrome/browser/extensions/extension_messages_apitest.cc
601@@ -1164,6 +1164,93 @@ IN_PROC_BROWSER_TEST_F(MessagingApiTest, MessagingUserGesture) {
602           "});", receiver->id().c_str())));
603 }
604
605+IN_PROC_BROWSER_TEST_F(MessagingApiTest,
606+                       RestrictedActivationTriggerBetweenExtensions) {
607+  base::CommandLine::ForCurrentProcess()->AppendSwitch(
608+      embedder_support::kDisablePopupBlocking);
609+
610+  const char kManifest[] = R"({
611+    "name": "activation_state_thru_send_reply",
612+    "version": "1.0",
613+    "background": {
614+      "scripts": ["background.js"]
615+    },
616+    "manifest_version": 2
617+  })";
618+
619+  // The receiver replies back with its transient activation state after a
620+  // delay.
621+  TestExtensionDir receiver_dir;
622+  receiver_dir.WriteManifest(kManifest);
623+  receiver_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
624+                         R"(
625+        chrome.runtime.onMessageExternal.addListener(
626+          (msg, sender, callback) => {
627+            setTimeout(() =>
628+              callback({active:navigator.userActivation.isActive}), 200);
629+          });
630+      )");
631+  const Extension* receiver = LoadExtension(receiver_dir.UnpackedPath());
632+  ASSERT_TRUE(receiver);
633+
634+  TestExtensionDir sender_dir;
635+  sender_dir.WriteManifest(kManifest);
636+  sender_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
637+  const Extension* sender = LoadExtension(sender_dir.UnpackedPath());
638+  ASSERT_TRUE(sender);
639+
640+  const char send_script_template[] = R"(
641+    log = [];
642+    log.push('sender-initial:' + navigator.userActivation.isActive);
643+    chrome.runtime.sendMessage('%s', {}, response => {
644+      log.push('receiver:' + response.active);
645+      log.push('sender-received:' + navigator.userActivation.isActive);
646+      window.domAutomationController.send(log.toString());
647+    });
648+    log.push('sender-sent:' + navigator.userActivation.isActive);
649+  )";
650+  std::string send_script =
651+      base::StringPrintf(send_script_template, receiver->id().c_str());
652+
653+  // Without any user activation, neither the sender nor the receiver should be
654+  // in active state at any moment.
655+  EXPECT_EQ(
656+      "sender-initial:false,sender-sent:false,receiver:false,"
657+      "sender-received:false",
658+      ExecuteScriptInBackgroundPage(
659+          sender->id(), send_script,
660+          extensions::browsertest_util::ScriptUserActivation::kDontActivate));
661+
662+  // With user activation before sending, the sender should be in active state
663+  // all the time, and the receiver should be in active state.
664+  //
665+  // TODO(crbug.com/957633): The receiver should be inactive here.
666+  EXPECT_EQ(
667+      "sender-initial:true,sender-sent:true,receiver:true,"
668+      "sender-received:true",
669+      ExecuteScriptInBackgroundPage(
670+          sender->id(), send_script,
671+          extensions::browsertest_util::ScriptUserActivation::kActivate));
672+
673+  std::string send_and_consume_script = send_script + R"(
674+    setTimeout(() => {
675+      open().close();
676+      log.push('sender-consumed:' + navigator.userActivation.isActive);
677+    }, 0);
678+  )";
679+
680+  // With user activation consumed right after sending, the sender should be in
681+  // active state until consumption, and the receiver should be in active state.
682+  //
683+  // TODO(crbug.com/957633): The receiver should be inactive here.
684+  EXPECT_EQ(
685+      "sender-initial:true,sender-sent:true,sender-consumed:false,"
686+      "receiver:true,sender-received:false",
687+      ExecuteScriptInBackgroundPage(
688+          sender->id(), send_and_consume_script,
689+          extensions::browsertest_util::ScriptUserActivation::kActivate));
690+}
691+
692 // Tests that a hosted app on a connectable site doesn't interfere with the
693 // connectability of that site.
694 IN_PROC_BROWSER_TEST_F(ExternallyConnectableMessagingTest, HostedAppOnWebsite) {
695diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
696index 94f799b5b4..fc54f9af7a 100644
697--- a/chrome/browser/external_protocol/external_protocol_handler.cc
698+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
699@@ -64,6 +64,7 @@ constexpr const char* kDeniedSchemes[] = {
700     "hcp",
701     "ie.http",
702     "javascript",
703+    "mk",
704     "ms-help",
705     "nntp",
706     "res",
707diff --git a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
708index 08d35a1844..1aa83951b3 100644
709--- a/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
710+++ b/chrome/browser/external_protocol/external_protocol_handler_unittest.cc
711@@ -347,6 +347,10 @@ TEST_F(ExternalProtocolHandlerTest, TestGetBlockStateDefaultBlock) {
712   block_state = ExternalProtocolHandler::GetBlockState("ie.http", nullptr,
713                                                        profile_.get());
714   EXPECT_EQ(ExternalProtocolHandler::BLOCK, block_state);
715+  EXPECT_EQ("mk", GURL("mk:@FooBar:ie.http:res://foo.bar/baz").scheme());
716+  block_state =
717+      ExternalProtocolHandler::GetBlockState("mk", nullptr, profile_.get());
718+  EXPECT_EQ(ExternalProtocolHandler::BLOCK, block_state);
719   EXPECT_TRUE(
720       profile_->GetPrefs()
721           ->GetDictionary(prefs::kProtocolHandlerPerOriginAllowedProtocols)
722diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
723index efcc2976aa..c012c830d9 100644
724--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
725+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
726@@ -2298,7 +2298,9 @@ void RenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
727       break;
728
729     case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
730-      OpenURLWithExtraHeaders(params_.link_url, GURL(),
731+      // Pass along the |referring_url| so we can show it in browser UI. Note
732+      // that this won't and shouldn't be sent via the referrer header.
733+      OpenURLWithExtraHeaders(params_.link_url, GetDocumentURL(params_),
734                               WindowOpenDisposition::OFF_THE_RECORD,
735                               ui::PAGE_TRANSITION_LINK, "" /* extra_headers */,
736                               true /* started_from_context_menu */);
737diff --git a/chrome/browser/signin/force_signin_verifier.cc b/chrome/browser/signin/force_signin_verifier.cc
738index 98671562c4..721e34340c 100644
739--- a/chrome/browser/signin/force_signin_verifier.cc
740+++ b/chrome/browser/signin/force_signin_verifier.cc
741@@ -64,7 +64,7 @@ void ForceSigninVerifier::OnAccessTokenFetchComplete(
742       backoff_request_timer_.Start(
743           FROM_HERE, backoff_entry_.GetTimeUntilRelease(),
744           base::BindOnce(&ForceSigninVerifier::SendRequest,
745-                         base::Unretained(this)));
746+                         weak_factory_.GetWeakPtr()));
747       access_token_fetcher_.reset();
748     }
749     return;
750@@ -105,7 +105,7 @@ void ForceSigninVerifier::SendRequest() {
751   if (content::GetNetworkConnectionTracker()->GetConnectionType(
752           &type,
753           base::BindOnce(&ForceSigninVerifier::SendRequestIfNetworkAvailable,
754-                         base::Unretained(this)))) {
755+                         weak_factory_.GetWeakPtr()))) {
756     SendRequestIfNetworkAvailable(type);
757   }
758 }
759@@ -119,13 +119,11 @@ void ForceSigninVerifier::SendRequestIfNetworkAvailable(
760
761   signin::ScopeSet oauth2_scopes;
762   oauth2_scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
763-  // It is safe to use Unretained(this) here given that the callback
764-  // will not be invoked if this object is deleted.
765   access_token_fetcher_ =
766       std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
767           "force_signin_verifier", identity_manager_, oauth2_scopes,
768           base::BindOnce(&ForceSigninVerifier::OnAccessTokenFetchComplete,
769-                         base::Unretained(this)),
770+                         weak_factory_.GetWeakPtr()),
771           signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
772 }
773
774diff --git a/chrome/browser/signin/force_signin_verifier.h b/chrome/browser/signin/force_signin_verifier.h
775index 6afd376297..70331bf90e 100644
776--- a/chrome/browser/signin/force_signin_verifier.h
777+++ b/chrome/browser/signin/force_signin_verifier.h
778@@ -76,6 +76,8 @@ class ForceSigninVerifier
779   base::TimeTicks creation_time_;
780
781   signin::IdentityManager* identity_manager_ = nullptr;
782+
783+  base::WeakPtrFactory<ForceSigninVerifier> weak_factory_{this};
784
785   DISALLOW_COPY_AND_ASSIGN(ForceSigninVerifier);
786 };
787diff --git a/chrome/browser/signin/force_signin_verifier_unittest.cc b/chrome/browser/signin/force_signin_verifier_unittest.cc
788index 3528d687d5..6771b0b850 100644
789--- a/chrome/browser/signin/force_signin_verifier_unittest.cc
790+++ b/chrome/browser/signin/force_signin_verifier_unittest.cc
791@@ -376,3 +376,28 @@ TEST(ForceSigninVerifierTest, ChangeNetworkFromWIFITo4GWithFinishedRequest) {
792   // No more request because it's verfied already.
793   EXPECT_EQ(nullptr, verifier.access_token_fetcher());
794 }
795+
796+// Regression test for https://crbug.com/1259864
797+TEST(ForceSigninVerifierTest, DeleteWithPendingRequestShouldNotCrash) {
798+  base::test::TaskEnvironment scoped_task_env;
799+  signin::IdentityTestEnvironment identity_test_env;
800+  const AccountInfo account_info =
801+      identity_test_env.MakePrimaryAccountAvailable(
802+          "email@test.com", signin::ConsentLevel::kSync);
803+
804+  ConfigureNetworkConnectionTracker(NetworkConnectionType::Undecided,
805+                                    NetworkResponseType::Asynchronous);
806+
807+  {
808+    ForceSigninVerifierWithAccessToInternalsForTesting verifier(
809+        identity_test_env.identity_manager());
810+
811+    // There is no network type at first.
812+    ASSERT_EQ(nullptr, verifier.access_token_fetcher());
813+
814+    // Delete the verifier while the request is pending.
815+  }
816+
817+  // Waiting for the network type returns, this should not crash.
818+  SpinCurrentSequenceTaskRunner();
819+}
820diff --git a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
821index 441d30c8d0..659af40f83 100644
822--- a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
823+++ b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.cc
824@@ -45,7 +45,7 @@ RecentlyUsedFoldersComboModel::Item::Item(const BookmarkNode* node,
825       type(type) {
826 }
827
828-RecentlyUsedFoldersComboModel::Item::~Item() {}
829+RecentlyUsedFoldersComboModel::Item::~Item() = default;
830
831 bool RecentlyUsedFoldersComboModel::Item::operator==(const Item& item) const {
832   return item.node == node && item.type == type;
833@@ -54,8 +54,7 @@ bool RecentlyUsedFoldersComboModel::Item::operator==(const Item& item) const {
834 RecentlyUsedFoldersComboModel::RecentlyUsedFoldersComboModel(
835     BookmarkModel* model,
836     const BookmarkNode* node)
837-    : bookmark_model_(model),
838-      node_parent_index_(0) {
839+    : bookmark_model_(model), parent_node_(node->parent()) {
840   bookmark_model_->AddObserver(this);
841   // Use + 2 to account for bookmark bar and other node.
842   std::vector<const BookmarkNode*> nodes =
843@@ -87,10 +86,6 @@ RecentlyUsedFoldersComboModel::RecentlyUsedFoldersComboModel(
844     items_.push_back(Item(model->mobile_node(), Item::TYPE_NODE));
845   items_.push_back(Item(NULL, Item::TYPE_SEPARATOR));
846   items_.push_back(Item(NULL, Item::TYPE_CHOOSE_ANOTHER_FOLDER));
847-
848-  auto it = std::find(items_.begin(), items_.end(),
849-                      Item(node->parent(), Item::TYPE_NODE));
850-  node_parent_index_ = static_cast<int>(it - items_.begin());
851 }
852
853 RecentlyUsedFoldersComboModel::~RecentlyUsedFoldersComboModel() {
854@@ -122,7 +117,16 @@ bool RecentlyUsedFoldersComboModel::IsItemSeparatorAt(int index) const {
855 }
856
857 int RecentlyUsedFoldersComboModel::GetDefaultIndex() const {
858-  return node_parent_index_;
859+  // TODO(pbos): Ideally we shouldn't have to handle `parent_node_` removal
860+  // here, the dialog should instead close immediately (and destroy `this`).
861+  // If that can be resolved, this should DCHECK that it != items_.end() and
862+  // a DCHECK should be added in the BookmarkModel observer methods to ensure
863+  // that we don't remove `parent_node_`.
864+  // TODO(pbos): Look at returning -1 here if there's no default index. Right
865+  // now a lot of code in Combobox assumes an index within `items_` bounds.
866+  auto it = std::find(items_.begin(), items_.end(),
867+                      Item(parent_node_, Item::TYPE_NODE));
868+  return it == items_.end() ? 0 : static_cast<int>(it - items_.begin());
869 }
870
871 void RecentlyUsedFoldersComboModel::AddObserver(
872@@ -222,6 +226,7 @@ void RecentlyUsedFoldersComboModel::BookmarkAllUserNodesRemoved(
873 void RecentlyUsedFoldersComboModel::MaybeChangeParent(
874     const BookmarkNode* node,
875     int selected_index) {
876+  DCHECK_LT(selected_index, static_cast<int>(items_.size()));
877   if (items_[selected_index].type != Item::TYPE_NODE)
878     return;
879
880@@ -234,7 +239,7 @@ void RecentlyUsedFoldersComboModel::MaybeChangeParent(
881
882 const BookmarkNode* RecentlyUsedFoldersComboModel::GetNodeAt(int index) {
883   if (index < 0 || index >= static_cast<int>(items_.size()))
884-    return NULL;
885+    return nullptr;
886   return items_[index].node;
887 }
888
889diff --git a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h
890index 6db8245e9d..1b6e8d0b9c 100644
891--- a/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h
892+++ b/chrome/browser/ui/bookmarks/recently_used_folders_combo_model.h
893@@ -83,10 +83,9 @@ class RecentlyUsedFoldersComboModel : public ui::ComboboxModel,
894   struct Item;
895   std::vector<Item> items_;
896
897-  bookmarks::BookmarkModel* bookmark_model_;
898+  bookmarks::BookmarkModel* const bookmark_model_;
899
900-  // The index of the original parent folder.
901-  int node_parent_index_;
902+  const bookmarks::BookmarkNode* const parent_node_;
903
904   base::ObserverList<ui::ComboboxModelObserver> observers_;
905
906diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
907index 4e8bc2e2ab..18a9372661 100644
908--- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
909+++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
910@@ -14,11 +14,15 @@
911 #include "chrome/browser/ui/test/test_browser_dialog.h"
912 #include "chrome/browser/ui/views/external_protocol_dialog.h"
913 #include "chrome/test/base/in_process_browser_test.h"
914+#include "chrome/test/base/ui_test_utils.h"
915 #include "content/public/browser/render_frame_host.h"
916 #include "content/public/browser/render_process_host.h"
917 #include "content/public/browser/render_view_host.h"
918 #include "content/public/browser/web_contents.h"
919 #include "content/public/test/browser_test.h"
920+#include "net/dns/mock_host_resolver.h"
921+#include "net/test/embedded_test_server/http_request.h"
922+#include "net/test/embedded_test_server/http_response.h"
923 #include "ui/views/controls/button/checkbox.h"
924 #include "url/gurl.h"
925
926@@ -41,6 +45,33 @@ class ExternalProtocolDialogTestApi {
927
928 }  // namespace test
929
930+namespace {
931+constexpr char kInitiatingOrigin[] = "a.test";
932+constexpr char kRedirectingOrigin[] = "b.test";
933+
934+class FakeDefaultProtocolClientWorker
935+    : public shell_integration::DefaultProtocolClientWorker {
936+ public:
937+  explicit FakeDefaultProtocolClientWorker(const std::string& protocol)
938+      : DefaultProtocolClientWorker(protocol) {}
939+  FakeDefaultProtocolClientWorker(const FakeDefaultProtocolClientWorker&) =
940+      delete;
941+  FakeDefaultProtocolClientWorker& operator=(
942+      const FakeDefaultProtocolClientWorker&) = delete;
943+
944+ private:
945+  ~FakeDefaultProtocolClientWorker() override = default;
946+  shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
947+    return shell_integration::DefaultWebClientState::NOT_DEFAULT;
948+  }
949+
950+  void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
951+    base::SequencedTaskRunnerHandle::Get()->PostTask(
952+        FROM_HERE, std::move(on_finished_callback));
953+  }
954+};
955+}  // namespace
956+
957 class ExternalProtocolDialogBrowserTest
958     : public DialogBrowserTest,
959       public ExternalProtocolHandler::Delegate {
960@@ -72,11 +103,11 @@ class ExternalProtocolDialogBrowserTest
961   // ExternalProtocolHander::Delegate:
962   scoped_refptr<shell_integration::DefaultProtocolClientWorker>
963   CreateShellWorker(const std::string& protocol) override {
964-    return nullptr;
965+    return base::MakeRefCounted<FakeDefaultProtocolClientWorker>(protocol);
966   }
967   ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
968                                                     Profile* profile) override {
969-    return ExternalProtocolHandler::DONT_BLOCK;
970+    return ExternalProtocolHandler::UNKNOWN;
971   }
972   void BlockRequest() override {}
973   void RunExternalProtocolDialog(
974@@ -84,7 +115,10 @@ class ExternalProtocolDialogBrowserTest
975       content::WebContents* web_contents,
976       ui::PageTransition page_transition,
977       bool has_user_gesture,
978-      const base::Optional<url::Origin>& initiating_origin) override {}
979+      const base::Optional<url::Origin>& initiating_origin) override {
980+        url_did_launch_ = true;
981+        launch_url_ = initiating_origin->host();
982+      }
983   void LaunchUrlWithoutSecurityCheck(
984       const GURL& url,
985       content::WebContents* web_contents) override {
986@@ -99,6 +133,12 @@ class ExternalProtocolDialogBrowserTest
987     blocked_state_ = state;
988   }
989
990+  void SetUpOnMainThread() override {
991+    DialogBrowserTest::SetUpOnMainThread();
992+    host_resolver()->AddRule(kInitiatingOrigin, "127.0.0.1");
993+    host_resolver()->AddRule(kRedirectingOrigin, "127.0.0.1");
994+  }
995+
996   base::HistogramTester histogram_tester_;
997
998  protected:
999@@ -107,6 +147,7 @@ class ExternalProtocolDialogBrowserTest
1000   url::Origin blocked_origin_;
1001   BlockState blocked_state_ = BlockState::UNKNOWN;
1002   bool url_did_launch_ = false;
1003+  std::string launch_url_;
1004
1005  private:
1006   DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialogBrowserTest);
1007@@ -232,3 +273,21 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestFocus) {
1008   const views::View* focused_view = focus_manager->GetFocusedView();
1009   EXPECT_TRUE(focused_view);
1010 }
1011+
1012+IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, OriginNameTest) {
1013+  ASSERT_TRUE(embedded_test_server()->Start());
1014+  content::WebContents* web_contents =
1015+      browser()->tab_strip_model()->GetActiveWebContents();
1016+  EXPECT_TRUE(ui_test_utils::NavigateToURL(
1017+      browser(), embedded_test_server()->GetURL("a.test", "/empty.html")));
1018+  EXPECT_TRUE(content::ExecJs(
1019+      web_contents,
1020+      content::JsReplace("location.href = $1",
1021+                         embedded_test_server()->GetURL(
1022+                             "b.test", "/server-redirect?ms-calc:"))));
1023+  content::WaitForLoadStop(web_contents);
1024+  EXPECT_TRUE(url_did_launch_);
1025+  // The url should be the url of the last redirecting server and not of the
1026+  // request initiator
1027+  EXPECT_EQ(launch_url_, "b.test");
1028+}
1029diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
1030index f22a3ce31b..fcdce3368a 100644
1031--- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
1032+++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
1033@@ -807,8 +807,15 @@ void WebUITabStripContainerView::ShowEditDialogForGroupAtPoint(
1034     tab_groups::TabGroupId group) {
1035   ConvertPointToScreen(this, &point);
1036   rect.set_origin(point);
1037-  TabGroupEditorBubbleView::Show(browser_view_->browser(), group, nullptr, rect,
1038-                                 this);
1039+  editor_bubble_widget_ = TabGroupEditorBubbleView::Show(
1040+      browser_view_->browser(), group, nullptr, rect, this);
1041+  scoped_widget_observation_.Observe(editor_bubble_widget_);
1042+}
1043+
1044+void WebUITabStripContainerView::HideEditDialogForGroup() {
1045+  if (editor_bubble_widget_)
1046+    editor_bubble_widget_->CloseWithReason(
1047+        BrowserFrame::ClosedReason::kUnspecified);
1048 }
1049
1050 TabStripUILayout WebUITabStripContainerView::GetLayout() {
1051@@ -907,6 +914,14 @@ void WebUITabStripContainerView::OnViewIsDeleting(View* observed_view) {
1052     tab_contents_container_ = nullptr;
1053 }
1054
1055+void WebUITabStripContainerView::OnWidgetDestroying(views::Widget* widget) {
1056+  if (widget != editor_bubble_widget_)
1057+    return;
1058+
1059+  scoped_widget_observation_.Reset();
1060+  editor_bubble_widget_ = nullptr;
1061+}
1062+
1063 bool WebUITabStripContainerView::SetPaneFocusAndFocusDefault() {
1064   // Make sure the pane first receives focus, then send a WebUI event to the
1065   // front-end so the correct HTML element receives focus.
1066diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h
1067index 536365f0a0..c5e03129ad 100644
1068--- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h
1069+++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h
1070@@ -23,6 +23,7 @@
1071 #include "ui/views/accessible_pane_view.h"
1072 #include "ui/views/view.h"
1073 #include "ui/views/widget/widget.h"
1074+#include "ui/views/widget/widget_observer.h"
1075
1076 #if !BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
1077 #error
1078@@ -47,6 +48,7 @@ class ImmersiveRevealedLock;
1079 class WebUITabStripContainerView : public TabStripUIEmbedder,
1080                                    public gfx::AnimationDelegate,
1081                                    public views::AccessiblePaneView,
1082+                                   public views::WidgetObserver,
1083                                    public views::ViewObserver {
1084  public:
1085   WebUITabStripContainerView(BrowserView* browser_view,
1086@@ -114,6 +116,7 @@ class WebUITabStripContainerView : public TabStripUIEmbedder,
1087   void ShowEditDialogForGroupAtPoint(gfx::Point point,
1088                                      gfx::Rect rect,
1089                                      tab_groups::TabGroupId group) override;
1090+  void HideEditDialogForGroup() override;
1091   TabStripUILayout GetLayout() override;
1092   SkColor GetColor(int id) const override;
1093   SkColor GetSystemColor(ui::NativeTheme::ColorId id) const override;
1094@@ -132,6 +135,9 @@ class WebUITabStripContainerView : public TabStripUIEmbedder,
1095   void OnViewBoundsChanged(View* observed_view) override;
1096   void OnViewIsDeleting(View* observed_view) override;
1097
1098+  // views::WidgetObserver:
1099+  void OnWidgetDestroying(views::Widget* widget) override;
1100+
1101   // views::AccessiblePaneView
1102   bool SetPaneFocusAndFocusDefault() override;
1103
1104@@ -171,6 +177,10 @@ class WebUITabStripContainerView : public TabStripUIEmbedder,
1105
1106   base::ScopedMultiSourceObservation<views::View, views::ViewObserver>
1107       view_observations_{this};
1108+  base::ScopedObservation<views::Widget, views::WidgetObserver>
1109+      scoped_widget_observation_{this};
1110+
1111+  views::Widget* editor_bubble_widget_;
1112 };
1113
1114 #endif  // CHROME_BROWSER_UI_VIEWS_FRAME_WEBUI_TAB_STRIP_CONTAINER_VIEW_H_
1115diff --git a/chrome/browser/ui/webui/discards/discards_ui.h b/chrome/browser/ui/webui/discards/discards_ui.h
1116index 9f9baf35a0..187dc9573a 100644
1117--- a/chrome/browser/ui/webui/discards/discards_ui.h
1118+++ b/chrome/browser/ui/webui/discards/discards_ui.h
1119@@ -37,7 +37,6 @@ class DiscardsUI : public ui::MojoWebUIController {
1120
1121  private:
1122   std::unique_ptr<discards::mojom::DetailsProvider> ui_handler_;
1123-  std::unique_ptr<discards::mojom::SiteDataProvider> site_data_provider_;
1124   std::string profile_id_;
1125
1126   WEB_UI_CONTROLLER_TYPE_DECL();
1127diff --git a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
1128index 0509d30670..eb980b3208 100644
1129--- a/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
1130+++ b/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc
1131@@ -136,7 +136,7 @@ void StartupPagesHandler::HandleEditStartupPage(const base::ListValue* args) {
1132   int index;
1133   CHECK(args->GetInteger(1, &index));
1134
1135-  if (index < 0 || index > startup_custom_pages_table_model_.RowCount()) {
1136+  if (index < 0 || index >= startup_custom_pages_table_model_.RowCount()) {
1137     RejectJavascriptCallback(*callback_id, base::Value());
1138     NOTREACHED();
1139     return;
1140diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
1141index 13f082cfbb..cb9a610cc2 100644
1142--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
1143+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
1144@@ -45,6 +45,7 @@ class MockTabStripUIEmbedder : public TabStripUIEmbedder {
1145                void(gfx::Point, std::unique_ptr<ui::MenuModel>));
1146   MOCK_METHOD3(ShowEditDialogForGroupAtPoint,
1147                void(gfx::Point, gfx::Rect, tab_groups::TabGroupId));
1148+  MOCK_METHOD0(HideEditDialogForGroup, void());
1149   MOCK_METHOD0(GetLayout, TabStripUILayout());
1150   MOCK_CONST_METHOD1(GetColor, SkColor(int));
1151   MOCK_CONST_METHOD1(GetSystemColor, SkColor(ui::NativeTheme::ColorId));
1152diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h
1153index 980326cb29..d04fd92537 100644
1154--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h
1155+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h
1156@@ -31,6 +31,8 @@ class TabStripUIEmbedder {
1157                                              gfx::Rect rect,
1158                                              tab_groups::TabGroupId group) = 0;
1159
1160+  virtual void HideEditDialogForGroup() = 0;
1161+
1162   virtual TabStripUILayout GetLayout() = 0;
1163
1164   virtual SkColor GetColor(int id) const = 0;
1165diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
1166index 3ef87b45d4..b56ce1f842 100644
1167--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
1168+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
1169@@ -228,6 +228,7 @@ void TabStripUIHandler::OnTabGroupChanged(const TabGroupChange& change) {
1170     }
1171
1172     case TabGroupChange::kClosed: {
1173+      embedder_->HideEditDialogForGroup();
1174       FireWebUIListener("tab-group-closed",
1175                         base::Value(change.group.ToString()));
1176       break;
1177diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
1178index 8dcd0c0a7d..77e9657606 100644
1179--- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
1180+++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
1181@@ -52,6 +52,7 @@ class StubTabStripUIEmbedder : public TabStripUIEmbedder {
1182                                      gfx::Rect rect,
1183                                      tab_groups::TabGroupId group_id) override {
1184   }
1185+  void HideEditDialogForGroup() override {}
1186   TabStripUILayout GetLayout() override { return TabStripUILayout(); }
1187   SkColor GetColor(int id) const override { return SK_ColorWHITE; }
1188   SkColor GetSystemColor(ui::NativeTheme::ColorId id) const override {
1189diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc
1190index eb5d6fc2d0..668ae8488d 100644
1191--- a/components/download/content/internal/download_driver_impl.cc
1192+++ b/components/download/content/internal/download_driver_impl.cc
1193@@ -176,6 +176,7 @@ void DownloadDriverImpl::Start(
1194   download_url_params->set_guid(guid);
1195   download_url_params->set_transient(true);
1196   download_url_params->set_method(request_params.method);
1197+  download_url_params->set_credentials_mode(request_params.credentials_mode);
1198   download_url_params->set_file_path(file_path);
1199   if (request_params.fetch_error_body)
1200     download_url_params->set_fetch_error_body(true);
1201@@ -189,6 +190,10 @@ void DownloadDriverImpl::Start(
1202                           weak_ptr_factory_.GetWeakPtr(), guid));
1203   download_url_params->set_require_safety_checks(
1204       request_params.require_safety_checks);
1205+  if (request_params.isolation_info) {
1206+    download_url_params->set_isolation_info(
1207+        request_params.isolation_info.value());
1208+  }
1209   download_manager_coordinator_->DownloadUrl(std::move(download_url_params));
1210 }
1211
1212diff --git a/components/download/database/DEPS b/components/download/database/DEPS
1213index 4e8777c36f..727aa9d8f9 100644
1214--- a/components/download/database/DEPS
1215+++ b/components/download/database/DEPS
1216@@ -1,5 +1,6 @@
1217 include_rules = [
1218   "+components/download/public/common",
1219   "+components/leveldb_proto",
1220-  "+services/metrics/public"
1221+  "+services/metrics/public",
1222+  "+services/network/public/mojom",
1223 ]
1224diff --git a/components/download/database/download_db_conversions.cc b/components/download/database/download_db_conversions.cc
1225index 2e6291671e..769db52d68 100644
1226--- a/components/download/database/download_db_conversions.cc
1227+++ b/components/download/database/download_db_conversions.cc
1228@@ -9,6 +9,7 @@
1229 #include "base/notreached.h"
1230 #include "base/pickle.h"
1231 #include "components/download/public/common/download_features.h"
1232+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1233
1234 namespace download {
1235 namespace {
1236@@ -218,7 +219,8 @@ download_pb::InProgressInfo DownloadDBConversions::InProgressInfoToProto(
1237             in_progress_info.download_schedule.value()));
1238     proto.set_allocated_download_schedule(download_schedule_proto.release());
1239   }
1240-
1241+  proto.set_credentials_mode(
1242+      static_cast<int32_t>(in_progress_info.credentials_mode));
1243   return proto;
1244 }
1245
1246@@ -275,6 +277,10 @@ InProgressInfo DownloadDBConversions::InProgressInfoFromProto(
1247         proto.download_schedule(), !proto.metered() /*only_on_wifi*/);
1248     DCHECK_NE(info.download_schedule->only_on_wifi(), info.metered);
1249   }
1250+  if (proto.has_credentials_mode()) {
1251+    info.credentials_mode = static_cast<::network::mojom::CredentialsMode>(
1252+        proto.credentials_mode());
1253+  }
1254
1255   return info;
1256 }
1257diff --git a/components/download/database/download_db_conversions_unittest.cc b/components/download/database/download_db_conversions_unittest.cc
1258index a2b80872d1..13d1513df0 100644
1259--- a/components/download/database/download_db_conversions_unittest.cc
1260+++ b/components/download/database/download_db_conversions_unittest.cc
1261@@ -9,6 +9,7 @@
1262 #include "components/download/public/common/download_features.h"
1263 #include "components/download/public/common/download_schedule.h"
1264 #include "components/download/public/common/download_url_parameters.h"
1265+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1266 #include "testing/gtest/include/gtest/gtest.h"
1267
1268 namespace download {
1269@@ -52,6 +53,7 @@ InProgressInfo CreateInProgressInfo() {
1270       std::make_pair<std::string, std::string>("ABC", "def"));
1271   info.download_schedule = base::make_optional<DownloadSchedule>(
1272       false /*only_on_wifi*/, base::nullopt);
1273+  info.credentials_mode = ::network::mojom::CredentialsMode::kOmit;
1274   return info;
1275 }
1276
1277diff --git a/components/download/database/in_progress/in_progress_info.cc b/components/download/database/in_progress/in_progress_info.cc
1278index 61a7afbd02..5ad63174a5 100644
1279--- a/components/download/database/in_progress/in_progress_info.cc
1280+++ b/components/download/database/in_progress/in_progress_info.cc
1281@@ -31,7 +31,8 @@ bool InProgressInfo::operator==(const InProgressInfo& other) const {
1282          interrupt_reason == other.interrupt_reason && paused == other.paused &&
1283          metered == other.metered && bytes_wasted == other.bytes_wasted &&
1284          auto_resume_count == other.auto_resume_count &&
1285-         download_schedule == other.download_schedule;
1286+         download_schedule == other.download_schedule &&
1287+         credentials_mode == other.credentials_mode;
1288 }
1289
1290 }  // namespace download
1291diff --git a/components/download/database/in_progress/in_progress_info.h b/components/download/database/in_progress/in_progress_info.h
1292index 2b67686c04..358964e32c 100644
1293--- a/components/download/database/in_progress/in_progress_info.h
1294+++ b/components/download/database/in_progress/in_progress_info.h
1295@@ -13,6 +13,7 @@
1296 #include "components/download/public/common/download_item.h"
1297 #include "components/download/public/common/download_schedule.h"
1298 #include "components/download/public/common/download_url_parameters.h"
1299+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1300 #include "url/gurl.h"
1301
1302 namespace download {
1303@@ -126,6 +127,10 @@ struct InProgressInfo {
1304
1305   // When to start the download. Used by download later feature.
1306   base::Optional<DownloadSchedule> download_schedule;
1307+
1308+  // The credentials mode of the request.
1309+  ::network::mojom::CredentialsMode credentials_mode =
1310+      ::network::mojom::CredentialsMode::kInclude;
1311 };
1312
1313 }  // namespace download
1314diff --git a/components/download/database/proto/download_entry.proto b/components/download/database/proto/download_entry.proto
1315index af78857228..8cbc590dfd 100644
1316--- a/components/download/database/proto/download_entry.proto
1317+++ b/components/download/database/proto/download_entry.proto
1318@@ -79,6 +79,7 @@ message InProgressInfo {
1319   optional int64 bytes_wasted = 26;
1320   optional int32 auto_resume_count = 27;
1321   optional DownloadSchedule download_schedule = 28;
1322+  optional int32 credentials_mode = 30;  // network::mojom::CredentialsMode
1323 }
1324
1325 // Stores various metadata related to a download.
1326diff --git a/components/download/internal/background_service/BUILD.gn b/components/download/internal/background_service/BUILD.gn
1327index e81d8f4668..6097be2417 100644
1328--- a/components/download/internal/background_service/BUILD.gn
1329+++ b/components/download/internal/background_service/BUILD.gn
1330@@ -89,6 +89,7 @@ static_library("internal") {
1331     "//components/download/public/background_service:public",
1332     "//components/leveldb_proto",
1333     "//net",
1334+    "//services/network/public/mojom:url_loader_base",
1335     "//services/network/public/cpp",
1336     "//storage/browser",
1337   ]
1338diff --git a/components/download/internal/background_service/in_memory_download.cc b/components/download/internal/background_service/in_memory_download.cc
1339index f5e369ff66..ccf54bdff7 100644
1340--- a/components/download/internal/background_service/in_memory_download.cc
1341+++ b/components/download/internal/background_service/in_memory_download.cc
1342@@ -204,6 +204,10 @@ void InMemoryDownloadImpl::SendRequest() {
1343     request->request_body = std::move(request_body_);
1344     request->enable_upload_progress = true;
1345   }
1346+  if (request_params_.isolation_info) {
1347+    request->site_for_cookies =
1348+        request_params_.isolation_info->site_for_cookies();
1349+  }
1350
1351   url_chain_.push_back(request_params_.url);
1352
1353diff --git a/components/download/internal/background_service/proto/request.proto b/components/download/internal/background_service/proto/request.proto
1354index 485bf6b6ae..346a201a5e 100644
1355--- a/components/download/internal/background_service/proto/request.proto
1356+++ b/components/download/internal/background_service/proto/request.proto
1357@@ -20,4 +20,5 @@ message RequestParams {
1358   repeated RequestHeader headers = 3;
1359   optional bool fetch_error_body = 4;
1360   optional bool require_safety_checks = 5 [default = true];
1361+  optional int32 credentials_mode = 6;  // network::mojom::CredentialsMode.
1362 }
1363diff --git a/components/download/internal/background_service/proto_conversions.cc b/components/download/internal/background_service/proto_conversions.cc
1364index 560fd484d0..1768714f0c 100644
1365--- a/components/download/internal/background_service/proto_conversions.cc
1366+++ b/components/download/internal/background_service/proto_conversions.cc
1367@@ -9,6 +9,7 @@
1368 #include "components/download/internal/background_service/proto_conversions.h"
1369 #include "net/http/http_request_headers.h"
1370 #include "net/traffic_annotation/network_traffic_annotation.h"
1371+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1372
1373 namespace download {
1374
1375@@ -250,6 +251,14 @@ RequestParams ProtoConversions::RequestParamsFromProto(
1376   request_params.method = proto.method();
1377   request_params.fetch_error_body = proto.fetch_error_body();
1378   request_params.require_safety_checks = proto.require_safety_checks();
1379+  if (proto.has_credentials_mode()) {
1380+    request_params.credentials_mode =
1381+        static_cast<::network::mojom::CredentialsMode>(
1382+            proto.credentials_mode());
1383+  } else {
1384+    request_params.credentials_mode =
1385+        ::network::mojom::CredentialsMode::kInclude;
1386+  }
1387
1388   for (int i = 0; i < proto.headers_size(); i++) {
1389     protodb::RequestHeader header = proto.headers(i);
1390@@ -265,6 +274,8 @@ void ProtoConversions::RequestParamsToProto(const RequestParams& request_params,
1391   proto->set_method(request_params.method);
1392   proto->set_fetch_error_body(request_params.fetch_error_body);
1393   proto->set_require_safety_checks(request_params.require_safety_checks);
1394+  proto->set_credentials_mode(
1395+      static_cast<int32_t>(request_params.credentials_mode));
1396
1397   int i = 0;
1398   net::HttpRequestHeaders::Iterator iter(request_params.request_headers);
1399diff --git a/components/download/internal/background_service/proto_conversions_unittest.cc b/components/download/internal/background_service/proto_conversions_unittest.cc
1400index 4307d0cbfd..ef4b561bff 100644
1401--- a/components/download/internal/background_service/proto_conversions_unittest.cc
1402+++ b/components/download/internal/background_service/proto_conversions_unittest.cc
1403@@ -9,6 +9,7 @@
1404 #include "components/download/internal/background_service/entry.h"
1405 #include "components/download/internal/background_service/proto_conversions.h"
1406 #include "components/download/internal/background_service/test/entry_utils.h"
1407+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1408 #include "testing/gtest/include/gtest/gtest.h"
1409
1410 namespace {
1411@@ -99,6 +100,7 @@ TEST_F(ProtoConversionsTest, RequestParamsWithHeadersConversion) {
1412   expected.method = "GET";
1413   expected.fetch_error_body = true;
1414   expected.require_safety_checks = false;
1415+  expected.credentials_mode = ::network::mojom::CredentialsMode::kInclude;
1416   expected.request_headers.SetHeader("key1", "value1");
1417   expected.request_headers.SetHeader("key2", "value2");
1418
1419@@ -110,6 +112,7 @@ TEST_F(ProtoConversionsTest, RequestParamsWithHeadersConversion) {
1420   EXPECT_EQ(expected.method, actual.method);
1421   EXPECT_EQ(expected.fetch_error_body, actual.fetch_error_body);
1422   EXPECT_EQ(expected.require_safety_checks, actual.require_safety_checks);
1423+  EXPECT_EQ(expected.credentials_mode, actual.credentials_mode);
1424
1425   std::string out;
1426   actual.request_headers.GetHeader("key1", &out);
1427@@ -120,6 +123,19 @@ TEST_F(ProtoConversionsTest, RequestParamsWithHeadersConversion) {
1428             actual.request_headers.ToString());
1429 }
1430
1431+TEST_F(ProtoConversionsTest, RequestParamsWithMissingCredentialsMode) {
1432+  RequestParams expected;
1433+  expected.url = GURL(TEST_URL);
1434+  expected.method = "GET";
1435+
1436+  protodb::RequestParams proto;
1437+  RequestParamsToProto(expected, &proto);
1438+  RequestParams actual = RequestParamsFromProto(proto);
1439+
1440+  EXPECT_EQ(expected.credentials_mode,
1441+            ::network::mojom::CredentialsMode::kInclude);
1442+}
1443+
1444 TEST_F(ProtoConversionsTest, EntryConversion) {
1445   Entry expected = test::BuildEntry(DownloadClient::TEST, base::GenerateGUID());
1446   Entry actual = EntryFromProto(EntryToProto(expected));
1447diff --git a/components/download/internal/common/download_create_info.cc b/components/download/internal/common/download_create_info.cc
1448index bba0342d59..c0c4f01d53 100644
1449--- a/components/download/internal/common/download_create_info.cc
1450+++ b/components/download/internal/common/download_create_info.cc
1451@@ -32,7 +32,9 @@ DownloadCreateInfo::DownloadCreateInfo(
1452       connection_info(net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN),
1453       method("GET"),
1454       ukm_source_id(ukm::kInvalidSourceId),
1455-      is_content_initiated(false) {}
1456+      is_content_initiated(false),
1457+      credentials_mode(::network::mojom::CredentialsMode::kInclude),
1458+      isolation_info(base::nullopt) {}
1459
1460 DownloadCreateInfo::DownloadCreateInfo()
1461     : DownloadCreateInfo(base::Time(), std::make_unique<DownloadSaveInfo>()) {}
1462diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
1463index f557ef8795..100493f1b5 100644
1464--- a/components/download/internal/common/download_item_impl.cc
1465+++ b/components/download/internal/common/download_item_impl.cc
1466@@ -234,7 +234,9 @@ DownloadItemImpl::RequestInfo::RequestInfo(
1467     ui::PageTransition transition_type,
1468     bool has_user_gesture,
1469     const std::string& remote_address,
1470-    base::Time start_time)
1471+    base::Time start_time,
1472+    ::network::mojom::CredentialsMode credentials_mode,
1473+    const base::Optional<net::IsolationInfo>& isolation_info)
1474     : url_chain(url_chain),
1475       referrer_url(referrer_url),
1476       site_url(site_url),
1477@@ -246,7 +248,9 @@ DownloadItemImpl::RequestInfo::RequestInfo(
1478       transition_type(transition_type),
1479       has_user_gesture(has_user_gesture),
1480       remote_address(remote_address),
1481-      start_time(start_time) {}
1482+      start_time(start_time),
1483+      credentials_mode(credentials_mode),
1484+      isolation_info(isolation_info) {}
1485
1486 DownloadItemImpl::RequestInfo::RequestInfo(const GURL& url)
1487     : url_chain(std::vector<GURL>(1, url)), start_time(base::Time::Now()) {}
1488@@ -328,7 +332,9 @@ DownloadItemImpl::DownloadItemImpl(
1489                     ui::PAGE_TRANSITION_LINK,
1490                     false,
1491                     std::string(),
1492-                    start_time),
1493+                    start_time,
1494+                    ::network::mojom::CredentialsMode::kInclude,
1495+                    base::nullopt),
1496       guid_(guid),
1497       download_id_(download_id),
1498       mime_type_(mime_type),
1499@@ -389,7 +395,9 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
1500                                          : ui::PAGE_TRANSITION_LINK,
1501                     info.has_user_gesture,
1502                     info.remote_address,
1503-                    info.start_time),
1504+                    info.start_time,
1505+                    info.credentials_mode,
1506+                    info.isolation_info),
1507       guid_(info.guid.empty() ? base::GenerateGUID() : info.guid),
1508       download_id_(download_id),
1509       response_headers_(info.response_headers),
1510@@ -1129,6 +1137,15 @@ const base::Optional<DownloadSchedule>& DownloadItemImpl::GetDownloadSchedule()
1511   return download_schedule_;
1512 }
1513
1514+::network::mojom::CredentialsMode DownloadItemImpl::GetCredentialsMode() const {
1515+  return request_info_.credentials_mode;
1516+}
1517+
1518+const base::Optional<net::IsolationInfo>& DownloadItemImpl::GetIsolationInfo()
1519+    const {
1520+  return request_info_.isolation_info;
1521+}
1522+
1523 void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type,
1524                                                DownloadInterruptReason reason) {
1525   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
1526diff --git a/components/download/internal/common/download_response_handler.cc b/components/download/internal/common/download_response_handler.cc
1527index a5f785aca0..8bdce0e0d2 100644
1528--- a/components/download/internal/common/download_response_handler.cc
1529+++ b/components/download/internal/common/download_response_handler.cc
1530@@ -75,6 +75,7 @@ DownloadResponseHandler::DownloadResponseHandler(
1531       request_origin_(request_origin),
1532       download_source_(download_source),
1533       has_strong_validators_(false),
1534+      credentials_mode_(resource_request->credentials_mode),
1535       is_partial_request_(save_info_->offset > 0),
1536       completed_(false),
1537       abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
1538@@ -84,6 +85,9 @@ DownloadResponseHandler::DownloadResponseHandler(
1539   }
1540   if (resource_request->request_initiator.has_value())
1541     request_initiator_ = resource_request->request_initiator;
1542+
1543+  if (resource_request->trusted_params)
1544+    isolation_info_ = resource_request->trusted_params->isolation_info;
1545 }
1546
1547 DownloadResponseHandler::~DownloadResponseHandler() = default;
1548@@ -150,6 +154,8 @@ DownloadResponseHandler::CreateDownloadCreateInfo(
1549   create_info->request_origin = request_origin_;
1550   create_info->download_source = download_source_;
1551   create_info->request_initiator = request_initiator_;
1552+  create_info->credentials_mode = credentials_mode_;
1553+  create_info->isolation_info = isolation_info_;
1554
1555   HandleResponseHeaders(head.headers.get(), create_info.get());
1556   return create_info;
1557diff --git a/components/download/internal/common/download_utils.cc b/components/download/internal/common/download_utils.cc
1558index 6ad1043959..5ef7d03541 100644
1559--- a/components/download/internal/common/download_utils.cc
1560+++ b/components/download/internal/common/download_utils.cc
1561@@ -438,6 +438,7 @@ DownloadDBEntry CreateDownloadDBEntryFromItem(const DownloadItemImpl& item) {
1562   in_progress_info.bytes_wasted = item.GetBytesWasted();
1563   in_progress_info.auto_resume_count = item.GetAutoResumeCount();
1564   in_progress_info.download_schedule = item.GetDownloadSchedule();
1565+  in_progress_info.credentials_mode = item.GetCredentialsMode();
1566
1567   download_info.in_progress_info = in_progress_info;
1568
1569diff --git a/components/download/public/background_service/BUILD.gn b/components/download/public/background_service/BUILD.gn
1570index 0e22c563e2..e4d3fad19b 100644
1571--- a/components/download/public/background_service/BUILD.gn
1572+++ b/components/download/public/background_service/BUILD.gn
1573@@ -27,7 +27,10 @@ source_set("public") {
1574     "service_config.h",
1575   ]
1576
1577-  deps = [ "//components/keyed_service/core" ]
1578+  deps = [
1579+     "//components/keyed_service/core",
1580+     "//services/network/public/mojom:url_loader_base",
1581+  ]
1582
1583   # TODO(xingliu): Create blob target that doesn't need to depend on blink.
1584   # Currently gn header check will fail even if the code is not built into any targets.
1585diff --git a/components/download/public/background_service/DEPS b/components/download/public/background_service/DEPS
1586index 4d8aa673f1..74b585b295 100644
1587--- a/components/download/public/background_service/DEPS
1588+++ b/components/download/public/background_service/DEPS
1589@@ -2,9 +2,11 @@ include_rules = [
1590   "-content",
1591   "+base",
1592   "+components/keyed_service",
1593+  "+net/base",
1594   "+net/http",
1595   "+net/traffic_annotation",
1596   "+services/network/public/cpp",
1597+  "+services/network/public/mojom",
1598   "+storage/browser",
1599   "+url",
1600 ]
1601diff --git a/components/download/public/background_service/download_params.cc b/components/download/public/background_service/download_params.cc
1602index 00a3ccbd9c..8a1a504a98 100644
1603--- a/components/download/public/background_service/download_params.cc
1604+++ b/components/download/public/background_service/download_params.cc
1605@@ -21,9 +21,13 @@ bool SchedulingParams::operator==(const SchedulingParams& rhs) const {
1606 }
1607
1608 RequestParams::RequestParams()
1609-    : method("GET"), fetch_error_body(false), require_safety_checks(true) {}
1610+    : method("GET"),
1611+      fetch_error_body(false),
1612+      require_safety_checks(true),
1613+      credentials_mode(::network::mojom::CredentialsMode::kInclude) {}
1614
1615 RequestParams::RequestParams(const RequestParams& other) = default;
1616+RequestParams::~RequestParams() = default;
1617
1618 DownloadParams::DownloadParams() : client(DownloadClient::INVALID) {}
1619
1620diff --git a/components/download/public/background_service/download_params.h b/components/download/public/background_service/download_params.h
1621index b16c150d8a..8aabeab939 100644
1622--- a/components/download/public/background_service/download_params.h
1623+++ b/components/download/public/background_service/download_params.h
1624@@ -8,8 +8,11 @@
1625 #include "base/callback.h"
1626 #include "base/time/time.h"
1627 #include "components/download/public/background_service/clients.h"
1628+#include "net/base/isolation_info.h"
1629 #include "net/http/http_request_headers.h"
1630 #include "net/traffic_annotation/network_traffic_annotation.h"
1631+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1632+#include "third_party/abseil-cpp/absl/types/optional.h"
1633 #include "url/gurl.h"
1634
1635 namespace download {
1636@@ -96,7 +99,7 @@ struct RequestParams {
1637  public:
1638   RequestParams();
1639   RequestParams(const RequestParams& other);
1640-  ~RequestParams() = default;
1641+  ~RequestParams();
1642
1643   GURL url;
1644
1645@@ -110,6 +113,12 @@ struct RequestParams {
1646
1647   // Whether the download is not trustworthy and requires safe browsing checks.
1648   bool require_safety_checks;
1649+
1650+  // The credentials mode of the request.
1651+  ::network::mojom::CredentialsMode credentials_mode;
1652+  // The isolation info of the request, this won't be persisted to db and will
1653+  // be invalidate during download resumption in new browser session.
1654+  base::Optional<net::IsolationInfo> isolation_info;
1655 };
1656
1657 // The parameters that describe a download request made to the DownloadService.
1658diff --git a/components/download/public/common/BUILD.gn b/components/download/public/common/BUILD.gn
1659index 3c8df71fb8..a0005014bf 100644
1660--- a/components/download/public/common/BUILD.gn
1661+++ b/components/download/public/common/BUILD.gn
1662@@ -79,6 +79,7 @@ component("public") {
1663     "//components/services/quarantine/public/mojom",
1664     "//mojo/public/cpp/bindings",
1665     "//services/network/public/cpp",
1666+    "//services/network/public/mojom:url_loader_base",
1667   ]
1668
1669   deps = [
1670diff --git a/components/download/public/common/download_create_info.h b/components/download/public/common/download_create_info.h
1671index b8c6e21b1b..51d58903e0 100644
1672--- a/components/download/public/common/download_create_info.h
1673+++ b/components/download/public/common/download_create_info.h
1674@@ -25,6 +25,7 @@
1675 #include "net/http/http_response_info.h"
1676 #include "net/url_request/referrer_policy.h"
1677 #include "services/metrics/public/cpp/ukm_source_id.h"
1678+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1679 #include "ui/base/page_transition_types.h"
1680 #include "url/gurl.h"
1681 #include "url/origin.h"
1682@@ -176,6 +177,11 @@ struct COMPONENTS_DOWNLOAD_EXPORT DownloadCreateInfo {
1683   // Whether download is initated by the content on the page.
1684   bool is_content_initiated;
1685
1686+  ::network::mojom::CredentialsMode credentials_mode;
1687+
1688+  // Isolation info for the download request, mainly for same site cookies.
1689+  base::Optional<net::IsolationInfo> isolation_info;
1690+
1691  private:
1692   DISALLOW_COPY_AND_ASSIGN(DownloadCreateInfo);
1693 };
1694diff --git a/components/download/public/common/download_item.h b/components/download/public/common/download_item.h
1695index b561de01fb..5d4f74b742 100644
1696--- a/components/download/public/common/download_item.h
1697+++ b/components/download/public/common/download_item.h
1698@@ -33,6 +33,8 @@
1699 #include "components/download/public/common/download_interrupt_reasons.h"
1700 #include "components/download/public/common/download_schedule.h"
1701 #include "components/download/public/common/download_source.h"
1702+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1703+#include "net/base/isolation_info.h"
1704 #include "ui/base/page_transition_types.h"
1705 #include "url/origin.h"
1706
1707@@ -351,6 +353,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItem : public base::SupportsUserData {
1708   // DownloadSource prompting this download.
1709   virtual DownloadSource GetDownloadSource() const = 0;
1710
1711+  // The credentials mode of the request.
1712+  virtual ::network::mojom::CredentialsMode GetCredentialsMode() const = 0;
1713+
1714+  // The isolation mode of the request.
1715+  virtual const base::Optional<net::IsolationInfo>& GetIsolationInfo()
1716+      const = 0;
1717+
1718   //    Destination State accessors --------------------------------------------
1719
1720   // Full path to the downloaded or downloading file. This is the path to the
1721diff --git a/components/download/public/common/download_item_impl.h b/components/download/public/common/download_item_impl.h
1722index 2868b25bd9..6d970f5630 100644
1723--- a/components/download/public/common/download_item_impl.h
1724+++ b/components/download/public/common/download_item_impl.h
1725@@ -31,6 +31,7 @@
1726 #include "components/download/public/common/url_loader_factory_provider.h"
1727 #include "mojo/public/cpp/bindings/pending_receiver.h"
1728 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
1729+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1730 #include "url/gurl.h"
1731 #include "url/origin.h"
1732
1733@@ -60,7 +61,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
1734                 ui::PageTransition transition_type,
1735                 bool has_user_gesture,
1736                 const std::string& remote_address,
1737-                base::Time start_time);
1738+                base::Time start_time,
1739+                ::network::mojom::CredentialsMode credentials_mode,
1740+                const base::Optional<net::IsolationInfo>& isolation_info);
1741     RequestInfo();
1742     explicit RequestInfo(const RequestInfo& other);
1743     explicit RequestInfo(const GURL& url);
1744@@ -104,6 +107,13 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
1745
1746     // Time the download was started.
1747     base::Time start_time;
1748+
1749+    // The credentials mode of the request.
1750+    ::network::mojom::CredentialsMode credentials_mode =
1751+        ::network::mojom::CredentialsMode::kInclude;
1752+
1753+    // Isolation info for the request.
1754+    base::Optional<net::IsolationInfo> isolation_info;
1755   };
1756
1757   // Information about the current state of the download destination.
1758@@ -301,6 +311,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadItemImpl
1759   bool IsParallelDownload() const override;
1760   DownloadCreationType GetDownloadCreationType() const override;
1761   const base::Optional<DownloadSchedule>& GetDownloadSchedule() const override;
1762+  ::network::mojom::CredentialsMode GetCredentialsMode() const override;
1763+  const base::Optional<net::IsolationInfo>& GetIsolationInfo() const override;
1764   void OnContentCheckCompleted(DownloadDangerType danger_type,
1765                                DownloadInterruptReason reason) override;
1766   void OnAsyncScanningCompleted(DownloadDangerType danger_type) override;
1767diff --git a/components/download/public/common/download_response_handler.h b/components/download/public/common/download_response_handler.h
1768index e7081025df..d39e0e1c7f 100644
1769--- a/components/download/public/common/download_response_handler.h
1770+++ b/components/download/public/common/download_response_handler.h
1771@@ -17,6 +17,7 @@
1772 #include "components/download/public/common/download_utils.h"
1773 #include "mojo/public/cpp/bindings/remote.h"
1774 #include "net/cert/cert_status_flags.h"
1775+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
1776 #include "services/network/public/mojom/url_loader.mojom.h"
1777 #include "services/network/public/mojom/url_response_head.mojom.h"
1778 #include "url/origin.h"
1779@@ -100,6 +101,8 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadResponseHandler
1780   net::CertStatus cert_status_;
1781   bool has_strong_validators_;
1782   base::Optional<url::Origin> request_initiator_;
1783+  ::network::mojom::CredentialsMode credentials_mode_;
1784+  base::Optional<net::IsolationInfo> isolation_info_;
1785   bool is_partial_request_;
1786   bool completed_;
1787
1788diff --git a/components/download/public/common/download_url_parameters.cc b/components/download/public/common/download_url_parameters.cc
1789index 0d898ac922..4ae3d9b207 100644
1790--- a/components/download/public/common/download_url_parameters.cc
1791+++ b/components/download/public/common/download_url_parameters.cc
1792@@ -19,6 +19,7 @@ DownloadUrlParameters::DownloadUrlParameters(
1793     : content_initiated_(false),
1794       use_if_range_(true),
1795       method_("GET"),
1796+      credentials_mode_(::network::mojom::CredentialsMode::kInclude),
1797       post_id_(-1),
1798       prefer_cache_(false),
1799       referrer_policy_(
1800diff --git a/components/download/public/common/download_url_parameters.h b/components/download/public/common/download_url_parameters.h
1801index 0be34e0e33..34dab4fae4 100644
1802--- a/components/download/public/common/download_url_parameters.h
1803+++ b/components/download/public/common/download_url_parameters.h
1804@@ -131,6 +131,12 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
1805   // HTTP method to use.
1806   void set_method(const std::string& method) { method_ = method; }
1807
1808+  // The requests' credentials mode.
1809+  void set_credentials_mode(
1810+      ::network::mojom::CredentialsMode credentials_mode) {
1811+    credentials_mode_ = credentials_mode;
1812+  }
1813+
1814   // Body of the HTTP POST request.
1815   void set_post_body(scoped_refptr<network::ResourceRequestBody> post_body) {
1816     post_body_ = post_body;
1817@@ -266,6 +272,9 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
1818   const std::string& etag() const { return etag_; }
1819   bool use_if_range() const { return use_if_range_; }
1820   const std::string& method() const { return method_; }
1821+  ::network::mojom::CredentialsMode credentials_mode() const {
1822+    return credentials_mode_;
1823+  }
1824   scoped_refptr<network::ResourceRequestBody> post_body() { return post_body_; }
1825   int64_t post_id() const { return post_id_; }
1826   bool prefer_cache() const { return prefer_cache_; }
1827@@ -331,6 +340,7 @@ class COMPONENTS_DOWNLOAD_EXPORT DownloadUrlParameters {
1828   std::string etag_;
1829   bool use_if_range_;
1830   std::string method_;
1831+  ::network::mojom::CredentialsMode credentials_mode_;
1832   scoped_refptr<network::ResourceRequestBody> post_body_;
1833   BlobStorageContextGetter blob_storage_context_getter_;
1834   int64_t post_id_;
1835diff --git a/components/download/public/common/mock_download_item.h b/components/download/public/common/mock_download_item.h
1836index 2ca3726cbe..3db623e279 100644
1837--- a/components/download/public/common/mock_download_item.h
1838+++ b/components/download/public/common/mock_download_item.h
1839@@ -127,6 +127,11 @@ class MockDownloadItem : public DownloadItem {
1840   MOCK_CONST_METHOD0(GetDownloadCreationType, DownloadCreationType());
1841   MOCK_CONST_METHOD0(GetDownloadSchedule,
1842                      const base::Optional<DownloadSchedule>&());
1843+  MOCK_CONST_METHOD0(GetCredentialsMode, ::network::mojom::CredentialsMode());
1844+  MOCK_METHOD((const base::Optional<net::IsolationInfo>&),
1845+            GetIsolationInfo,
1846+            (),
1847+            (const override));
1848   MOCK_METHOD2(OnContentCheckCompleted,
1849                void(DownloadDangerType, DownloadInterruptReason));
1850   MOCK_METHOD1(SetOpenWhenComplete, void(bool));
1851diff --git a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
1852index 60212cae10..ade80fca4f 100644
1853--- a/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
1854+++ b/components/page_load_metrics/browser/observers/back_forward_cache_page_load_metrics_observer.cc
1855@@ -77,6 +77,8 @@ void BackForwardCachePageLoadMetricsObserver::
1856     OnFirstPaintAfterBackForwardCacheRestoreInPage(
1857         const page_load_metrics::mojom::BackForwardCacheTiming& timing,
1858         size_t index) {
1859+  if (index >= back_forward_cache_navigation_ids_.size())
1860+    return;
1861   auto first_paint = timing.first_paint_after_back_forward_cache_restore;
1862   DCHECK(!first_paint.is_zero());
1863   if (page_load_metrics::
1864@@ -109,6 +111,8 @@ void BackForwardCachePageLoadMetricsObserver::
1865     OnRequestAnimationFramesAfterBackForwardCacheRestoreInPage(
1866         const page_load_metrics::mojom::BackForwardCacheTiming& timing,
1867         size_t index) {
1868+  if (index >= back_forward_cache_navigation_ids_.size())
1869+    return;
1870   auto request_animation_frames =
1871       timing.request_animation_frames_after_back_forward_cache_restore;
1872   DCHECK_EQ(request_animation_frames.size(), 3u);
1873@@ -143,6 +147,8 @@ void BackForwardCachePageLoadMetricsObserver::
1874     OnFirstInputAfterBackForwardCacheRestoreInPage(
1875         const page_load_metrics::mojom::BackForwardCacheTiming& timing,
1876         size_t index) {
1877+  if (index >= back_forward_cache_navigation_ids_.size())
1878+    return;
1879   auto first_input_delay =
1880       timing.first_input_delay_after_back_forward_cache_restore;
1881   DCHECK(first_input_delay.has_value());
1882diff --git a/components/page_load_metrics/browser/page_load_tracker.cc b/components/page_load_metrics/browser/page_load_tracker.cc
1883index 846cfaa16b..f02129066b 100644
1884--- a/components/page_load_metrics/browser/page_load_tracker.cc
1885+++ b/components/page_load_metrics/browser/page_load_tracker.cc
1886@@ -12,6 +12,7 @@
1887 #include "base/check_op.h"
1888 #include "base/metrics/histogram_macros.h"
1889 #include "base/notreached.h"
1890+#include "base/strings/stringprintf.h"
1891 #include "base/time/default_tick_clock.h"
1892 #include "base/trace_event/trace_event.h"
1893 #include "components/page_load_metrics/browser/page_load_metrics_embedder_interface.h"
1894@@ -129,7 +130,13 @@ void DispatchEventsAfterBackForwardCacheRestore(
1895         last_timings,
1896     const std::vector<mojo::StructPtr<mojom::BackForwardCacheTiming>>&
1897         new_timings) {
1898-  DCHECK_GE(new_timings.size(), last_timings.size());
1899+  if (new_timings.size() < last_timings.size()) {
1900+    mojo::ReportBadMessage(base::StringPrintf(
1901+        "`new_timings.size()` (%zu) must be equal to or greater than "
1902+        "`last_timings.size()` (%zu) but is not",
1903+        new_timings.size(), last_timings.size()));
1904+    return;
1905+  }
1906
1907   for (size_t i = 0; i < new_timings.size(); i++) {
1908     auto first_paint =
1909diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
1910index 3222c0aef7..269e76928d 100644
1911--- a/components/pdf/renderer/pdf_accessibility_tree.cc
1912+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
1913@@ -1486,9 +1486,16 @@ content::RenderAccessibility* PdfAccessibilityTree::GetRenderAccessibility() {
1914   // If RenderAccessibility is unable to generate valid positive IDs,
1915   // we shouldn't use it. This can happen if Blink accessibility is disabled
1916   // after we started generating the accessible PDF.
1917+  base::WeakPtr<PdfAccessibilityTree> weak_this =
1918+      weak_ptr_factory_.GetWeakPtr();
1919   if (render_accessibility->GenerateAXID() <= 0)
1920     return nullptr;
1921
1922+  // GenerateAXID() above can cause self deletion. Returning nullptr will cause
1923+  // callers to stop doing work.
1924+  if (!weak_this)
1925+    return nullptr;
1926+
1927   return render_accessibility;
1928 }
1929
1930diff --git a/components/pdf/renderer/pdf_accessibility_tree.h b/components/pdf/renderer/pdf_accessibility_tree.h
1931index 16331d527b..55038a28bd 100644
1932--- a/components/pdf/renderer/pdf_accessibility_tree.h
1933+++ b/components/pdf/renderer/pdf_accessibility_tree.h
1934@@ -11,6 +11,7 @@
1935 #include <vector>
1936
1937 #include "base/optional.h"
1938+#include "base/memory/weak_ptr.h"
1939 #include "content/public/renderer/plugin_ax_tree_source.h"
1940 #include "ppapi/c/pp_instance.h"
1941 #include "ppapi/c/private/ppb_pdf.h"
1942@@ -171,6 +172,8 @@ class PdfAccessibilityTree : public content::PluginAXTreeSource {
1943   // Index of the next expected PDF accessibility page info, used to ignore
1944   // outdated calls of SetAccessibilityPageInfo().
1945   uint32_t next_page_index_ = 0;
1946+
1947+  base::WeakPtrFactory<PdfAccessibilityTree> weak_ptr_factory_{this};
1948 };
1949
1950 }  // namespace pdf
1951diff --git a/components/performance_manager/decorators/site_data_recorder_unittest.cc b/components/performance_manager/decorators/site_data_recorder_unittest.cc
1952index 003bea3d06..909533f41a 100644
1953--- a/components/performance_manager/decorators/site_data_recorder_unittest.cc
1954+++ b/components/performance_manager/decorators/site_data_recorder_unittest.cc
1955@@ -89,8 +89,9 @@ class MockDataCache : public SiteDataCache {
1956   }
1957   std::unique_ptr<SiteDataWriter> GetWriterForOrigin(
1958       const url::Origin& origin) override {
1959-    scoped_refptr<internal::SiteDataImpl> fake_impl = base::WrapRefCounted(
1960-        new internal::SiteDataImpl(origin, &delegate_, &data_store_));
1961+    scoped_refptr<internal::SiteDataImpl> fake_impl =
1962+        base::WrapRefCounted(new internal::SiteDataImpl(
1963+            origin, delegate_.GetWeakPtr(), &data_store_));
1964
1965     return std::make_unique<MockDataWriter>(origin, fake_impl);
1966   }
1967diff --git a/components/performance_manager/persistence/site_data/site_data_cache_impl.cc b/components/performance_manager/persistence/site_data/site_data_cache_impl.cc
1968index e936a16c5d..547de3ca48 100644
1969--- a/components/performance_manager/persistence/site_data/site_data_cache_impl.cc
1970+++ b/components/performance_manager/persistence/site_data/site_data_cache_impl.cc
1971@@ -122,8 +122,8 @@ internal::SiteDataImpl* SiteDataCacheImpl::GetOrCreateFeatureImpl(
1972     return iter->second;
1973
1974   // If not create a new one and add it to the map.
1975-  internal::SiteDataImpl* site_data =
1976-      new internal::SiteDataImpl(origin, this, data_store_.get());
1977+  internal::SiteDataImpl* site_data = new internal::SiteDataImpl(
1978+      origin, weak_factory_.GetWeakPtr(), data_store_.get());
1979
1980   // internal::SiteDataImpl is a ref-counted object, it's safe to store a raw
1981   // pointer to it here as this class will get notified when it's about to be
1982diff --git a/components/performance_manager/persistence/site_data/site_data_cache_impl.h b/components/performance_manager/persistence/site_data/site_data_cache_impl.h
1983index c21c0bf72f..f7b6c462a5 100644
1984--- a/components/performance_manager/persistence/site_data/site_data_cache_impl.h
1985+++ b/components/performance_manager/persistence/site_data/site_data_cache_impl.h
1986@@ -15,6 +15,7 @@
1987 #include "base/files/file_path.h"
1988 #include "base/gtest_prod_util.h"
1989 #include "base/macros.h"
1990+#include "base/memory/weak_ptr.h"
1991 #include "base/scoped_observation.h"
1992 #include "base/sequence_checker.h"
1993 #include "components/performance_manager/persistence/site_data/site_data_cache.h"
1994@@ -102,6 +103,8 @@ class SiteDataCacheImpl : public SiteDataCache,
1995
1996   SEQUENCE_CHECKER(sequence_checker_);
1997
1998+  base::WeakPtrFactory<SiteDataCacheImpl> weak_factory_{this};
1999+
2000   DISALLOW_COPY_AND_ASSIGN(SiteDataCacheImpl);
2001 };
2002
2003diff --git a/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc b/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
2004index 54c692ef96..26ee928101 100644
2005--- a/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
2006+++ b/components/performance_manager/persistence/site_data/site_data_cache_impl_unittest.cc
2007@@ -269,4 +269,19 @@ TEST_F(SiteDataCacheImplTest, InspectorWorks) {
2008                 browser_context_.UniqueId()));
2009 }
2010
2011+// TODO(https://crbug.com/1231933): Turn this into a death test to verify that
2012+//     the data cache asserts that no readers outlive the cache.
2013+TEST_F(SiteDataCacheImplTest, NoUAFWhenReaderHeldAfterTeardown) {
2014+  {
2015+    // Hold on to this reader while destroying the data cache.
2016+    // This is a violation of the data cache contract. For the purpose
2017+    // of quick-fixing https://crbug.com/1231933, allow and survive this
2018+    // for now.
2019+    auto reader = data_cache_->GetReaderForOrigin(origin_);
2020+
2021+    // This should not UAF under ASAN.
2022+    data_cache_.reset();
2023+  }
2024+}
2025+
2026 }  // namespace performance_manager
2027diff --git a/components/performance_manager/persistence/site_data/site_data_impl.cc b/components/performance_manager/persistence/site_data/site_data_impl.cc
2028index eeb4a5da4c..738021a00a 100644
2029--- a/components/performance_manager/persistence/site_data/site_data_impl.cc
2030+++ b/components/performance_manager/persistence/site_data/site_data_impl.cc
2031@@ -169,7 +169,7 @@ SiteDataImpl::GetFeatureObservationWindowLengthForTesting() {
2032 }
2033
2034 SiteDataImpl::SiteDataImpl(const url::Origin& origin,
2035-                           OnDestroyDelegate* delegate,
2036+                           base::WeakPtr<OnDestroyDelegate> delegate,
2037                            SiteDataStore* data_store)
2038     : load_duration_(kSampleWeightFactor),
2039       cpu_usage_estimate_(kSampleWeightFactor),
2040@@ -198,13 +198,19 @@ SiteDataImpl::~SiteDataImpl() {
2041   DCHECK(!IsLoaded());
2042   DCHECK_EQ(0U, loaded_tabs_in_background_count_);
2043
2044-  DCHECK(delegate_);
2045-  delegate_->OnSiteDataImplDestroyed(this);
2046-
2047-  // TODO(sebmarchand): Some data might be lost here if the read operation has
2048-  // not completed, add some metrics to measure if this is really an issue.
2049-  if (is_dirty_ && fully_initialized_)
2050-    data_store_->WriteSiteDataIntoStore(origin_, FlushStateToProto());
2051+  // Make sure not to dispatch a notification to a deleted delegate, and gate
2052+  // the DB write on it too, as the delegate and the data store have the
2053+  // same lifetime.
2054+  // TODO(https://crbug.com/1231933): Fix this properly and restore the end of
2055+  //     life write here.
2056+  if (delegate_) {
2057+    delegate_->OnSiteDataImplDestroyed(this);
2058+
2059+    // TODO(sebmarchand): Some data might be lost here if the read operation has
2060+    // not completed, add some metrics to measure if this is really an issue.
2061+    if (is_dirty_ && fully_initialized_)
2062+      data_store_->WriteSiteDataIntoStore(origin_, FlushStateToProto());
2063+  }
2064 }
2065
2066 base::TimeDelta SiteDataImpl::FeatureObservationDuration(
2067diff --git a/components/performance_manager/persistence/site_data/site_data_impl.h b/components/performance_manager/persistence/site_data/site_data_impl.h
2068index f48c7dd1a7..c50fe64925 100644
2069--- a/components/performance_manager/persistence/site_data/site_data_impl.h
2070+++ b/components/performance_manager/persistence/site_data/site_data_impl.h
2071@@ -172,7 +172,7 @@ class SiteDataImpl : public base::RefCounted<SiteDataImpl> {
2072   friend class performance_manager::MockDataCache;
2073
2074   SiteDataImpl(const url::Origin& origin,
2075-               OnDestroyDelegate* delegate,
2076+               base::WeakPtr<OnDestroyDelegate> delegate,
2077                SiteDataStore* data_store);
2078
2079   virtual ~SiteDataImpl();
2080@@ -283,7 +283,13 @@ class SiteDataImpl : public base::RefCounted<SiteDataImpl> {
2081
2082   // The delegate that should get notified when this object is about to get
2083   // destroyed, it should outlive this object.
2084-  OnDestroyDelegate* const delegate_;
2085+  // The use of WeakPtr here is a temporary, minimally invasive fix for the UAF
2086+  // reported in https://crbug.com/1231933. By using a WeakPtr, the call-out
2087+  // is avoided in the case where the OnDestroyDelegate has been deleted before
2088+  // all SiteDataImpls have been released.
2089+  // The proper fix for this is going to be more invasive and less suitable
2090+  // for merging, should it come to that.
2091+  base::WeakPtr<OnDestroyDelegate> const delegate_;
2092
2093   // Indicates if this object has been fully initialized, either because the
2094   // read operation from the database has completed or because it has been
2095diff --git a/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc b/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
2096index 90edb917b2..0ce8da8a0b 100644
2097--- a/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
2098+++ b/components/performance_manager/persistence/site_data/site_data_impl_unittest.cc
2099@@ -26,9 +26,10 @@ class TestSiteDataImpl : public SiteDataImpl {
2100   using SiteDataImpl::site_characteristics_for_testing;
2101   using SiteDataImpl::TimeDeltaToInternalRepresentation;
2102
2103-  explicit TestSiteDataImpl(const url::Origin& origin,
2104-                            SiteDataImpl::OnDestroyDelegate* delegate,
2105-                            SiteDataStore* data_store)
2106+  explicit TestSiteDataImpl(
2107+      const url::Origin& origin,
2108+      base::WeakPtr<SiteDataImpl::OnDestroyDelegate> delegate,
2109+      SiteDataStore* data_store)
2110       : SiteDataImpl(origin, delegate, data_store) {}
2111
2112   base::TimeDelta FeatureObservationTimestamp(
2113@@ -90,7 +91,7 @@ class SiteDataImplTest : public ::testing::Test {
2114
2115   scoped_refptr<TestSiteDataImpl> GetDataImpl(
2116       const url::Origin& origin,
2117-      SiteDataImpl::OnDestroyDelegate* destroy_delegate,
2118+      base::WeakPtr<SiteDataImpl::OnDestroyDelegate> destroy_delegate,
2119       SiteDataStore* data_store) {
2120     return base::MakeRefCounted<TestSiteDataImpl>(origin, destroy_delegate,
2121                                                   data_store);
2122@@ -100,7 +101,7 @@ class SiteDataImplTest : public ::testing::Test {
2123   // locally so it can be run later.
2124   scoped_refptr<TestSiteDataImpl> GetDataImplAndInterceptReadCallback(
2125       const url::Origin& origin,
2126-      SiteDataImpl::OnDestroyDelegate* destroy_delegate,
2127+      base::WeakPtr<SiteDataImpl::OnDestroyDelegate> destroy_delegate,
2128       MockDataStore* mock_data_store,
2129       SiteDataStore::ReadSiteDataFromStoreCallback* read_cb) {
2130     auto read_from_store_mock_impl =
2131@@ -113,7 +114,7 @@ class SiteDataImplTest : public ::testing::Test {
2132                 OnReadSiteDataFromStore(::testing::_, ::testing::_))
2133         .WillOnce(::testing::Invoke(read_from_store_mock_impl));
2134     auto local_site_data =
2135-        GetDataImpl(origin, &destroy_delegate_, mock_data_store);
2136+        GetDataImpl(origin, destroy_delegate_.GetWeakPtr(), mock_data_store);
2137     ::testing::Mock::VerifyAndClear(mock_data_store);
2138     return local_site_data;
2139   }
2140@@ -134,7 +135,7 @@ class SiteDataImplTest : public ::testing::Test {
2141
2142 TEST_F(SiteDataImplTest, BasicTestEndToEnd) {
2143   auto local_site_data =
2144-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2145+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2146
2147   local_site_data->NotifySiteLoaded();
2148   local_site_data->NotifyLoadedSiteBackgrounded();
2149@@ -191,7 +192,7 @@ TEST_F(SiteDataImplTest, BasicTestEndToEnd) {
2150
2151 TEST_F(SiteDataImplTest, LastLoadedTime) {
2152   auto local_site_data =
2153-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2154+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2155
2156   // Create a second instance of this object, simulates having several tab
2157   // owning it.
2158@@ -222,7 +223,7 @@ TEST_F(SiteDataImplTest, LastLoadedTime) {
2159
2160 TEST_F(SiteDataImplTest, GetFeatureUsageForUnloadedSite) {
2161   auto local_site_data =
2162-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2163+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2164
2165   local_site_data->NotifySiteLoaded();
2166   local_site_data->NotifyLoadedSiteBackgrounded();
2167@@ -275,7 +276,7 @@ TEST_F(SiteDataImplTest, AllDurationGetSavedOnUnload) {
2168   // This test helps making sure that the observation/timestamp fields get saved
2169   // for all the features being tracked.
2170   auto local_site_data =
2171-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2172+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2173
2174   const base::TimeDelta kInterval = base::TimeDelta::FromSeconds(1);
2175   const auto kIntervalInternalRepresentation =
2176@@ -340,7 +341,7 @@ TEST_F(SiteDataImplTest, DestroyNotifiesDelegate) {
2177       strict_delegate;
2178   {
2179     auto local_site_data =
2180-        GetDataImpl(kDummyOrigin, &strict_delegate, &data_store);
2181+        GetDataImpl(kDummyOrigin, strict_delegate.GetWeakPtr(), &data_store);
2182     EXPECT_CALL(strict_delegate,
2183                 OnSiteDataImplDestroyed(local_site_data.get()));
2184   }
2185@@ -357,7 +358,7 @@ TEST_F(SiteDataImplTest, OnInitCallbackMergePreviousObservations) {
2186   SiteDataStore::ReadSiteDataFromStoreCallback read_cb;
2187
2188   auto local_site_data = GetDataImplAndInterceptReadCallback(
2189-      kDummyOrigin, &destroy_delegate_, &mock_data_store, &read_cb);
2190+      kDummyOrigin, destroy_delegate_.GetWeakPtr(), &mock_data_store, &read_cb);
2191
2192   // Simulates audio in background usage before the callback gets called.
2193   local_site_data->NotifySiteLoaded();
2194@@ -481,7 +482,7 @@ TEST_F(SiteDataImplTest, LateAsyncReadDoesntEraseData) {
2195   SiteDataStore::ReadSiteDataFromStoreCallback read_cb;
2196
2197   auto local_site_data_writer = GetDataImplAndInterceptReadCallback(
2198-      kDummyOrigin, &destroy_delegate_, &mock_data_store, &read_cb);
2199+      kDummyOrigin, destroy_delegate_.GetWeakPtr(), &mock_data_store, &read_cb);
2200
2201   local_site_data_writer->NotifySiteLoaded();
2202   local_site_data_writer->NotifyLoadedSiteBackgrounded();
2203@@ -510,7 +511,7 @@ TEST_F(SiteDataImplTest, LateAsyncReadDoesntBypassClearEvent) {
2204   SiteDataStore::ReadSiteDataFromStoreCallback read_cb;
2205
2206   auto local_site_data = GetDataImplAndInterceptReadCallback(
2207-      kDummyOrigin, &destroy_delegate_, &mock_data_store, &read_cb);
2208+      kDummyOrigin, destroy_delegate_.GetWeakPtr(), &mock_data_store, &read_cb);
2209
2210   local_site_data->NotifySiteLoaded();
2211   local_site_data->NotifyLoadedSiteBackgrounded();
2212@@ -527,7 +528,7 @@ TEST_F(SiteDataImplTest, LateAsyncReadDoesntBypassClearEvent) {
2213
2214 TEST_F(SiteDataImplTest, BackgroundedCountTests) {
2215   auto local_site_data =
2216-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2217+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2218
2219   // By default the tabs are expected to be foregrounded.
2220   EXPECT_EQ(0U, local_site_data->loaded_tabs_in_background_count_for_testing());
2221@@ -585,7 +586,7 @@ TEST_F(SiteDataImplTest, OptionalFieldsNotPopulatedWhenClean) {
2222   SiteDataStore::ReadSiteDataFromStoreCallback read_cb;
2223
2224   auto local_site_data = GetDataImplAndInterceptReadCallback(
2225-      kDummyOrigin, &destroy_delegate_, &mock_data_store, &read_cb);
2226+      kDummyOrigin, destroy_delegate_.GetWeakPtr(), &mock_data_store, &read_cb);
2227
2228   EXPECT_EQ(0u, local_site_data->cpu_usage_estimate().num_datums());
2229   EXPECT_EQ(0u, local_site_data->private_footprint_kb_estimate().num_datums());
2230@@ -622,9 +623,9 @@ TEST_F(SiteDataImplTest, FlushingStateToProtoDoesntAffectData) {
2231   // calling FlushStateToProto doesn't affect the data that gets recorded.
2232
2233   auto local_site_data =
2234-      GetDataImpl(kDummyOrigin, &destroy_delegate_, &data_store);
2235+      GetDataImpl(kDummyOrigin, destroy_delegate_.GetWeakPtr(), &data_store);
2236   auto local_site_data_ref =
2237-      GetDataImpl(kDummyOrigin2, &destroy_delegate_, &data_store);
2238+      GetDataImpl(kDummyOrigin2, destroy_delegate_.GetWeakPtr(), &data_store);
2239
2240   local_site_data->NotifySiteLoaded();
2241   local_site_data->NotifyLoadedSiteBackgrounded();
2242@@ -663,7 +664,7 @@ TEST_F(SiteDataImplTest, DataLoadedCallbackInvoked) {
2243   SiteDataStore::ReadSiteDataFromStoreCallback read_cb;
2244
2245   auto local_site_data = GetDataImplAndInterceptReadCallback(
2246-      kDummyOrigin, &destroy_delegate_, &mock_data_store, &read_cb);
2247+      kDummyOrigin, destroy_delegate_.GetWeakPtr(), &mock_data_store, &read_cb);
2248
2249   EXPECT_FALSE(local_site_data->DataLoaded());
2250
2251diff --git a/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc b/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
2252index 7145a122c9..e3b85b5e6e 100644
2253--- a/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
2254+++ b/components/performance_manager/persistence/site_data/site_data_reader_unittest.cc
2255@@ -71,8 +71,9 @@ class SiteDataReaderTest : public ::testing::Test {
2256   // SiteDataImpl is protected and not visible to
2257   // base::MakeRefCounted.
2258   SiteDataReaderTest() {
2259-    test_impl_ = base::WrapRefCounted(new internal::SiteDataImpl(
2260-        url::Origin::Create(GURL("foo.com")), &delegate_, &data_store_));
2261+    test_impl_ = base::WrapRefCounted(
2262+        new internal::SiteDataImpl(url::Origin::Create(GURL("foo.com")),
2263+                                   delegate_.GetWeakPtr(), &data_store_));
2264     test_impl_->NotifySiteLoaded();
2265     test_impl_->NotifyLoadedSiteBackgrounded();
2266     SiteDataReader* reader = new SiteDataReader(test_impl_.get());
2267@@ -153,9 +154,9 @@ TEST_F(SiteDataReaderTest, FreeingReaderDoesntCauseWriteOperation) {
2268                               ::testing::_))
2269       .WillOnce(::testing::Invoke(read_from_store_mock_impl));
2270
2271-  std::unique_ptr<SiteDataReader> reader =
2272-      base::WrapUnique(new SiteDataReader(base::WrapRefCounted(
2273-          new internal::SiteDataImpl(kOrigin, &delegate_, &data_store))));
2274+  std::unique_ptr<SiteDataReader> reader = base::WrapUnique(
2275+      new SiteDataReader(base::WrapRefCounted(new internal::SiteDataImpl(
2276+          kOrigin, delegate_.GetWeakPtr(), &data_store))));
2277   ::testing::Mock::VerifyAndClear(&data_store);
2278
2279   EXPECT_TRUE(reader->impl_for_testing()->fully_initialized_for_testing());
2280@@ -177,7 +178,7 @@ TEST_F(SiteDataReaderTest, OnDataLoadedCallbackInvoked) {
2281                                                   kOrigin.Serialize()),
2282                               ::testing::_));
2283   scoped_refptr<internal::SiteDataImpl> impl = base::WrapRefCounted(
2284-      new internal::SiteDataImpl(kOrigin, &delegate_, &data_store));
2285+      new internal::SiteDataImpl(kOrigin, delegate_.GetWeakPtr(), &data_store));
2286
2287   // Create the reader.
2288   std::unique_ptr<SiteDataReader> reader =
2289@@ -208,7 +209,7 @@ TEST_F(SiteDataReaderTest, DestroyingReaderCancelsPendingCallbacks) {
2290                                                   kOrigin.Serialize()),
2291                               ::testing::_));
2292   scoped_refptr<internal::SiteDataImpl> impl = base::WrapRefCounted(
2293-      new internal::SiteDataImpl(kOrigin, &delegate_, &data_store));
2294+      new internal::SiteDataImpl(kOrigin, delegate_.GetWeakPtr(), &data_store));
2295
2296   // Create the reader.
2297   std::unique_ptr<SiteDataReader> reader =
2298diff --git a/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc b/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc
2299index 272089fd17..bc5500237b 100644
2300--- a/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc
2301+++ b/components/performance_manager/persistence/site_data/site_data_writer_unittest.cc
2302@@ -24,7 +24,7 @@ class SiteDataWriterTest : public ::testing::Test {
2303   SiteDataWriterTest()
2304       : test_impl_(base::WrapRefCounted(
2305             new internal::SiteDataImpl(url::Origin::Create(GURL("foo.com")),
2306-                                       &delegate_,
2307+                                       delegate_.GetWeakPtr(),
2308                                        &data_store_))) {
2309     SiteDataWriter* writer = new SiteDataWriter(test_impl_.get());
2310     writer_ = base::WrapUnique(writer);
2311diff --git a/components/performance_manager/persistence/site_data/unittest_utils.h b/components/performance_manager/persistence/site_data/unittest_utils.h
2312index a5451e4fb3..75d7d698e7 100644
2313--- a/components/performance_manager/persistence/site_data/unittest_utils.h
2314+++ b/components/performance_manager/persistence/site_data/unittest_utils.h
2315@@ -9,6 +9,7 @@
2316 #include <vector>
2317
2318 #include "base/macros.h"
2319+#include "base/memory/weak_ptr.h"
2320 #include "components/performance_manager/performance_manager_impl.h"
2321 #include "components/performance_manager/persistence/site_data/site_data_impl.h"
2322 #include "components/performance_manager/persistence/site_data/site_data_store.h"
2323@@ -27,7 +28,13 @@ class MockSiteDataImplOnDestroyDelegate
2324
2325   MOCK_METHOD1(OnSiteDataImplDestroyed, void(internal::SiteDataImpl*));
2326
2327+  base::WeakPtr<MockSiteDataImplOnDestroyDelegate> GetWeakPtr() {
2328+    return weak_factory_.GetWeakPtr();
2329+  }
2330+
2331  private:
2332+  base::WeakPtrFactory<MockSiteDataImplOnDestroyDelegate> weak_factory_{this};
2333+
2334   DISALLOW_COPY_AND_ASSIGN(MockSiteDataImplOnDestroyDelegate);
2335 };
2336
2337diff --git a/components/permissions/permission_request_manager.cc b/components/permissions/permission_request_manager.cc
2338index f3148d318d..f41c73a8fc 100644
2339--- a/components/permissions/permission_request_manager.cc
2340+++ b/components/permissions/permission_request_manager.cc
2341@@ -545,13 +545,13 @@ void PermissionRequestManager::ScheduleDequeueRequestIfNeeded() {
2342 }
2343
2344 void PermissionRequestManager::ShowBubble() {
2345-  // There is a race condition where the request might have been removed already
2346-  // so double-checking that there is a request in progress (crbug.com/1041222).
2347-  if (!IsRequestInProgress())
2348+  // There is a race condition where the request might have been removed
2349+  // already so double-checking that there is a request in progress.
2350+  //
2351+  // There is no need to show a new bubble if the previous one still exists.
2352+  if (!IsRequestInProgress() || view_)
2353     return;
2354
2355-  DCHECK(!requests_.empty());
2356-  DCHECK(!view_);
2357   DCHECK(web_contents()->IsDocumentOnLoadCompletedInMainFrame());
2358   DCHECK(current_request_ui_to_use_);
2359
2360diff --git a/components/renderer_context_menu/render_view_context_menu_base.cc b/components/renderer_context_menu/render_view_context_menu_base.cc
2361index bb98c91e7c..3250f7d556 100644
2362--- a/components/renderer_context_menu/render_view_context_menu_base.cc
2363+++ b/components/renderer_context_menu/render_view_context_menu_base.cc
2364@@ -466,9 +466,14 @@ void RenderViewContextMenuBase::OpenURLWithExtraHeaders(
2365     ui::PageTransition transition,
2366     const std::string& extra_headers,
2367     bool started_from_context_menu) {
2368+  // Do not send the referrer url to OTR windows. We still need the
2369+  // |referring_url| to populate the |initiator_origin| below for browser UI.
2370+  GURL referrer_url;
2371+  if (disposition != WindowOpenDisposition::OFF_THE_RECORD)
2372+    referrer_url = referring_url.GetAsReferrer();
2373+
2374   content::Referrer referrer = content::Referrer::SanitizeForRequest(
2375-      url, content::Referrer(referring_url.GetAsReferrer(),
2376-                             params_.referrer_policy));
2377+      url, content::Referrer(referrer_url, params_.referrer_policy));
2378
2379   if (params_.link_url == url &&
2380       disposition != WindowOpenDisposition::OFF_THE_RECORD)
2381diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
2382index 9974db23eb..50ac01b8f5 100644
2383--- a/content/app/content_main_runner_impl.cc
2384+++ b/content/app/content_main_runner_impl.cc
2385@@ -106,6 +106,7 @@
2386 #include "ui/base/ui_base_switches.h"
2387 #include "ui/display/display_switches.h"
2388 #include "ui/gfx/switches.h"
2389+#include "content/renderer/render_remote_proxy.h"
2390
2391 #if defined(OS_WIN)
2392 #include <malloc.h>
2393@@ -909,6 +910,11 @@ int ContentMainRunnerImpl::Run(bool start_minimal_browser) {
2394     if (process_type != switches::kZygoteProcess) {
2395       // Zygotes will run this at a later point in time when the command line
2396       // has been updated.
2397+#if defined(OS_OHOS)
2398+      if (!RunRenderRemoteProxy(command_line)) {
2399+        return -1;
2400+      }
2401+#endif
2402       InitializeFieldTrialAndFeatureList();
2403       delegate_->PostFieldTrialInitialization();
2404
2405@@ -1068,6 +1074,22 @@ int ContentMainRunnerImpl::RunBrowser(MainFunctionParams& main_params,
2406   return RunBrowserProcessMain(main_params, delegate_);
2407 }
2408
2409+#if defined(OS_OHOS)
2410+bool ContentMainRunnerImpl::RunRenderRemoteProxy(
2411+    const base::CommandLine& command_line) {
2412+  std::string process_type =
2413+      command_line.GetSwitchValueASCII(switches::kProcessType);
2414+  if (process_type != switches::kRendererProcess) {
2415+    return true;
2416+  }
2417+  RenderRemoteProxy::CreateAndRegist(command_line);
2418+  if (!RenderRemoteProxy::WaitForBrowserFd()) {
2419+    return false;
2420+  }
2421+  return true;
2422+}
2423+#endif
2424+
2425 void ContentMainRunnerImpl::Shutdown() {
2426   DCHECK(is_initialized_);
2427   DCHECK(!is_shutdown_);
2428diff --git a/content/app/content_main_runner_impl.h b/content/app/content_main_runner_impl.h
2429index 090171f7db..6bef22cb2f 100644
2430--- a/content/app/content_main_runner_impl.h
2431+++ b/content/app/content_main_runner_impl.h
2432@@ -58,6 +58,9 @@ class CONTENT_EXPORT ContentMainRunnerImpl : public ContentMainRunner {
2433  private:
2434   int RunBrowser(MainFunctionParams& main_function_params,
2435                  bool start_minimal_browser);
2436+#if defined(OS_OHOS)
2437+  bool RunRenderRemoteProxy(const base::CommandLine& command_line);
2438+#endif
2439
2440   bool is_browser_main_loop_started_ = false;
2441
2442diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
2443index 50d79fe628..1fcc93ffdd 100644
2444--- a/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
2445+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.cc
2446@@ -7,6 +7,7 @@
2447 #include <set>
2448
2449 #include "base/strings/string_split.h"
2450+#include "base/strings/string_util.h"
2451 #include "content/browser/background_fetch/background_fetch_request_info.h"
2452 #include "url/gurl.h"
2453
2454@@ -15,6 +16,8 @@ namespace content {
2455 namespace {
2456
2457 const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin";
2458+const char kAccessControlAllowCredentialsHeader[] =
2459+    "access-control-allow-credentials";
2460 const char kAnyOriginValue[] = "*";
2461
2462 // Parses the header list (including "any origin") value from a given response
2463@@ -67,20 +70,29 @@ BackgroundFetchCrossOriginFilter::BackgroundFetchCrossOriginFilter(
2464       response_header_map.find(kAccessControlAllowOriginHeader);
2465
2466   if (access_control_allow_origin_iter != response_header_map.end()) {
2467-    bool access_control_allow_any_origin = false;
2468     std::set<url::Origin> access_control_allow_origins;
2469
2470     if (ParseOriginListHeader(access_control_allow_origin_iter->second,
2471-                              &access_control_allow_any_origin,
2472+                              &access_control_allow_origin_any_,
2473                               &access_control_allow_origins)) {
2474-      access_control_allow_origin_ =
2475-          access_control_allow_any_origin ||
2476+      access_control_allow_origin_exact_ =
2477           access_control_allow_origins.count(source_origin) == 1;
2478     }
2479   }
2480
2481-  // TODO(crbug.com/711354): Consider the Access-Control-Allow-Credentials
2482-  //                         header.
2483+  // Access-Control-Allow-Credentials checks. The header's values must be valid
2484+  // for it to not be completely discarded.
2485+  auto access_control_allow_credentials_iter =
2486+      response_header_map.find(kAccessControlAllowCredentialsHeader);
2487+  if (access_control_allow_credentials_iter != response_header_map.end()) {
2488+    access_control_allow_credentials_ =
2489+        base::ToLowerASCII(access_control_allow_credentials_iter->second) ==
2490+        "true";
2491+  }
2492+
2493+  include_credentials_ = request.fetch_request()->credentials_mode ==
2494+                         ::network::mojom::CredentialsMode::kInclude;
2495+
2496   // TODO(crbug.com/711354): Consider the Access-Control-Allow-Headers header.
2497   // TODO(crbug.com/711354): Consider the Access-Control-Allow-Methods header.
2498   // TODO(crbug.com/711354): Consider the Access-Control-Expose-Headers header.
2499@@ -89,12 +101,28 @@ BackgroundFetchCrossOriginFilter::BackgroundFetchCrossOriginFilter(
2500 BackgroundFetchCrossOriginFilter::~BackgroundFetchCrossOriginFilter() = default;
2501
2502 bool BackgroundFetchCrossOriginFilter::CanPopulateBody() const {
2503-  // The body will be populated if:
2504-  //   (1) The source and the response share their origin.
2505-  //   (2) The Access-Control-Allow-Origin method allows any origin.
2506-  //   (3) The Access-Control-Allow-Origin method allows the source origin.
2507+  if (is_same_origin_) {
2508+    // Same origin requests are always OK.
2509+    return true;
2510+  }
2511+
2512+  // For cross-origin requests, the body will be populated if:
2513+
2514+  // (1) The Access-Control-Allow-Origin method allows the source origin / any
2515+  //     origin.
2516+  if (!access_control_allow_origin_exact_ &&
2517+      !access_control_allow_origin_any_) {
2518+    return false;
2519+  }
2520+
2521+  // (2) For requests with credentials, the Access-Control-Allow-Credentials is
2522+  //     set and the Access-Control-Allow-Origin contains the exact origin.
2523+  if (include_credentials_ && (!access_control_allow_credentials_ ||
2524+                               !access_control_allow_origin_exact_)) {
2525+    return false;
2526+  }
2527
2528-  return is_same_origin_ || access_control_allow_origin_;
2529+  return true;
2530 }
2531
2532 }  // namespace content
2533diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter.h b/content/browser/background_fetch/background_fetch_cross_origin_filter.h
2534index 042856bb56..20e14c2240 100644
2535--- a/content/browser/background_fetch/background_fetch_cross_origin_filter.h
2536+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter.h
2537@@ -32,8 +32,19 @@ class CONTENT_EXPORT BackgroundFetchCrossOriginFilter {
2538   // Whether the response comes from the same origin as the requester.
2539   bool is_same_origin_ = false;
2540
2541-  // Whether the Access-Control-Allow-Origin header includes the source origin.
2542-  bool access_control_allow_origin_ = false;
2543+  // Whether the Access-Control-Allow-Origin header includes the exact source
2544+  // origin.
2545+  bool access_control_allow_origin_exact_ = false;
2546+
2547+  // Whether the Access-Control-Allow-Origin header includes any source origin
2548+  // (*).
2549+  bool access_control_allow_origin_any_ = false;
2550+
2551+  // Whether the Access-Control-Allow-Credentials header is included.
2552+  bool access_control_allow_credentials_ = false;
2553+
2554+  // Whether credentials were included for cross-origin requests.
2555+  bool include_credentials_ = false;
2556
2557   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchCrossOriginFilter);
2558 };
2559diff --git a/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
2560index ace470460c..7c5e41055e 100644
2561--- a/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
2562+++ b/content/browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc
2563@@ -20,6 +20,8 @@ const char kFirstOriginFile[] = "https://example.com/cat.jpg";
2564 const char kSecondOriginFile[] = "https://chrome.com/cat.jpg";
2565
2566 const char kAccessControlAllowOriginHeader[] = "access-control-allow-origin";
2567+const char kAccessControlAllowCredentialsHeader[] =
2568+    "access-control-allow-credentials";
2569
2570 class BackgroundFetchCrossOriginFilterTest : public ::testing::Test {
2571  public:
2572@@ -35,7 +37,8 @@ class BackgroundFetchCrossOriginFilterTest : public ::testing::Test {
2573       const char* response_url,
2574       std::initializer_list<
2575           typename std::map<std::string, std::string>::value_type>
2576-          response_headers) {
2577+          response_headers,
2578+      bool allow_credentials = false) {
2579     scoped_refptr<BackgroundFetchRequestInfo> request_info =
2580         base::MakeRefCounted<BackgroundFetchRequestInfo>(
2581             0 /* request_info */, blink::mojom::FetchAPIRequest::New(),
2582@@ -43,6 +46,13 @@ class BackgroundFetchCrossOriginFilterTest : public ::testing::Test {
2583
2584     request_info->response_headers_ = response_headers;
2585     request_info->url_chain_ = {GURL(response_url)};
2586+    if (allow_credentials) {
2587+      request_info->fetch_request()->credentials_mode =
2588+          network::mojom::CredentialsMode::kInclude;
2589+    } else {
2590+      request_info->fetch_request()->credentials_mode =
2591+          network::mojom::CredentialsMode::kSameOrigin;
2592+    }
2593
2594     return request_info;
2595   }
2596@@ -113,4 +123,54 @@ TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginAllowSpecificOrigin) {
2597   }
2598 }
2599
2600+TEST_F(BackgroundFetchCrossOriginFilterTest, CrossOriginCredentials) {
2601+  // 1: No headers.
2602+  {
2603+    auto request =
2604+        CreateRequestInfo(kSecondOriginFile, {}, /*include_credentials=*/true);
2605+    BackgroundFetchCrossOriginFilter filter(source_, *request);
2606+    EXPECT_FALSE(filter.CanPopulateBody());
2607+  }
2608+
2609+  // 2: Valid request.
2610+  {
2611+    auto request =
2612+        CreateRequestInfo(kSecondOriginFile,
2613+                          {{kAccessControlAllowOriginHeader, kFirstOrigin},
2614+                           {kAccessControlAllowCredentialsHeader, "true"}},
2615+                          /*include_credentials=*/true);
2616+    BackgroundFetchCrossOriginFilter filter(source_, *request);
2617+    EXPECT_TRUE(filter.CanPopulateBody());
2618+  }
2619+
2620+  // 3: Missing ACAO Header.
2621+  {
2622+    auto request = CreateRequestInfo(
2623+        kSecondOriginFile, {{kAccessControlAllowCredentialsHeader, "true"}},
2624+        /*include_credentials=*/true);
2625+    BackgroundFetchCrossOriginFilter filter(source_, *request);
2626+    EXPECT_FALSE(filter.CanPopulateBody());
2627+  }
2628+
2629+  // 4: Missing ACAC header.
2630+  {
2631+    auto request = CreateRequestInfo(
2632+        kSecondOriginFile, {{kAccessControlAllowOriginHeader, kFirstOrigin}},
2633+        /*include_credentials=*/true);
2634+    BackgroundFetchCrossOriginFilter filter(source_, *request);
2635+    EXPECT_FALSE(filter.CanPopulateBody());
2636+  }
2637+
2638+  // 5: ACAO any origin.
2639+  {
2640+    auto request =
2641+        CreateRequestInfo(kSecondOriginFile,
2642+                          {{kAccessControlAllowOriginHeader, "*"},
2643+                           {kAccessControlAllowCredentialsHeader, "true"}},
2644+                          /*include_credentials=*/true);
2645+    BackgroundFetchCrossOriginFilter filter(source_, *request);
2646+    EXPECT_FALSE(filter.CanPopulateBody());
2647+  }
2648+}
2649+
2650 }  // namespace content
2651diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy.cc b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
2652index 7fdbb99fbc..efcbcfcc19 100644
2653--- a/content/browser/background_fetch/background_fetch_delegate_proxy.cc
2654+++ b/content/browser/background_fetch/background_fetch_delegate_proxy.cc
2655@@ -160,7 +160,8 @@ class BackgroundFetchDelegateProxy::Core
2656
2657     delegate->DownloadUrl(
2658         job_unique_id, request->download_guid(), fetch_request->method,
2659-        fetch_request->url, traffic_annotation, headers,
2660+        fetch_request->url, fetch_request->credentials_mode, traffic_annotation,
2661+        headers,
2662         /* has_request_body= */ request->request_body_size() > 0u);
2663   }
2664
2665diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
2666index 9564453073..3a1d773294 100644
2667--- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
2668+++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
2669@@ -55,6 +55,7 @@ class FakeBackgroundFetchDelegate : public BackgroundFetchDelegate {
2670                    const std::string& guid,
2671                    const std::string& method,
2672                    const GURL& url,
2673+                   ::network::mojom::CredentialsMode credentials_mode,
2674                    const net::NetworkTrafficAnnotationTag& traffic_annotation,
2675                    const net::HttpRequestHeaders& headers,
2676                    bool has_request_body) override {
2677diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
2678index f424cadba0..0d08d1f744 100644
2679--- a/content/browser/background_fetch/background_fetch_job_controller.cc
2680+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
2681@@ -173,6 +173,8 @@ void BackgroundFetchJobController::DidStartRequest(
2682   // TODO(crbug.com/884672): Stop the fetch if the cross origin filter fails.
2683   BackgroundFetchCrossOriginFilter filter(registration_id_.origin(), *request);
2684   request->set_can_populate_body(filter.CanPopulateBody());
2685+  if (!request->can_populate_body())
2686+    has_failed_cors_request_ = true;
2687 }
2688
2689 void BackgroundFetchJobController::DidUpdateRequest(const std::string& guid,
2690@@ -253,7 +255,14 @@ uint64_t BackgroundFetchJobController::GetInProgressUploadedBytes() {
2691
2692 void BackgroundFetchJobController::AbortFromDelegate(
2693     BackgroundFetchFailureReason failure_reason) {
2694-  failure_reason_ = failure_reason;
2695+  if (failure_reason == BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED &&
2696+      has_failed_cors_request_) {
2697+    // Don't expose that the download total has been exceeded. Use a less
2698+    // specific error.
2699+    failure_reason_ = BackgroundFetchFailureReason::FETCH_ERROR;
2700+  } else {
2701+    failure_reason_ = failure_reason;
2702+  }
2703
2704   Finish(failure_reason_, base::DoNothing());
2705 }
2706diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h
2707index e635c86c1e..66a1c94e9d 100644
2708--- a/content/browser/background_fetch/background_fetch_job_controller.h
2709+++ b/content/browser/background_fetch/background_fetch_job_controller.h
2710@@ -210,6 +210,10 @@ class CONTENT_EXPORT BackgroundFetchJobController
2711   blink::mojom::BackgroundFetchFailureReason failure_reason_ =
2712       blink::mojom::BackgroundFetchFailureReason::NONE;
2713
2714+  // Whether one of the requests handled by the controller failed
2715+  // the CORS checks and should not have its response exposed.
2716+  bool has_failed_cors_request_ = false;
2717+
2718   // Custom callback that runs after the controller is finished.
2719   FinishedCallback finished_callback_;
2720
2721diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
2722index ad9a313672..eb0e8fc337 100644
2723--- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
2724+++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
2725@@ -433,6 +433,39 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
2726             GetCompletionStatus(registration_id));
2727 }
2728
2729+TEST_F(BackgroundFetchJobControllerTest, AbortDownloadExceededCrossOrigin) {
2730+  BackgroundFetchRegistrationId registration_id;
2731+
2732+  auto requests = CreateRegistrationForRequests(
2733+      &registration_id, {{GURL("https://example2.com/funny_cat.png"), "GET"}},
2734+      /* auto_complete_requests= */ true);
2735+
2736+  EXPECT_EQ(JobCompletionStatus::kRunning,
2737+            GetCompletionStatus(registration_id));
2738+
2739+  std::unique_ptr<BackgroundFetchJobController> controller =
2740+      CreateJobController(registration_id, requests.size());
2741+
2742+  controller->StartRequest(requests[0], base::DoNothing());
2743+
2744+  controller->DidStartRequest(
2745+      requests[0]->download_guid(),
2746+      std::make_unique<BackgroundFetchResponse>(
2747+          std::vector<GURL>{GURL("https://example2.com/funny_cat.png")},
2748+          nullptr));
2749+  EXPECT_FALSE(requests[0]->can_populate_body());
2750+
2751+  controller->AbortFromDelegate(
2752+      blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);
2753+
2754+  base::RunLoop().RunUntilIdle();
2755+
2756+  EXPECT_EQ(JobCompletionStatus::kAborted,
2757+            GetCompletionStatus(registration_id));
2758+  EXPECT_EQ(finished_requests_[registration_id],
2759+            blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR);
2760+}
2761+
2762 TEST_F(BackgroundFetchJobControllerTest, Progress) {
2763   BackgroundFetchRegistrationId registration_id;
2764
2765diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.cc b/content/browser/background_fetch/mock_background_fetch_delegate.cc
2766index 4ebfb985b7..c4bbfe9f43 100644
2767--- a/content/browser/background_fetch/mock_background_fetch_delegate.cc
2768+++ b/content/browser/background_fetch/mock_background_fetch_delegate.cc
2769@@ -88,6 +88,7 @@ void MockBackgroundFetchDelegate::DownloadUrl(
2770     const std::string& guid,
2771     const std::string& method,
2772     const GURL& url,
2773+    ::network::mojom::CredentialsMode credentials_mode,
2774     const net::NetworkTrafficAnnotationTag& traffic_annotation,
2775     const net::HttpRequestHeaders& headers,
2776     bool has_request_body) {
2777diff --git a/content/browser/background_fetch/mock_background_fetch_delegate.h b/content/browser/background_fetch/mock_background_fetch_delegate.h
2778index 499bca6eb7..8796655b9c 100644
2779--- a/content/browser/background_fetch/mock_background_fetch_delegate.h
2780+++ b/content/browser/background_fetch/mock_background_fetch_delegate.h
2781@@ -80,6 +80,7 @@ class MockBackgroundFetchDelegate : public BackgroundFetchDelegate {
2782                    const std::string& guid,
2783                    const std::string& method,
2784                    const GURL& url,
2785+                   ::network::mojom::CredentialsMode credentials_mode,
2786                    const net::NetworkTrafficAnnotationTag& traffic_annotation,
2787                    const net::HttpRequestHeaders& headers,
2788                    bool has_request_body) override;
2789diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
2790index c27331d1cb..583e54e218 100644
2791--- a/content/browser/bad_message.h
2792+++ b/content/browser/bad_message.h
2793@@ -268,6 +268,7 @@ enum BadMessageReason {
2794   WCI_INVALID_FULLSCREEN_OPTIONS = 240,
2795   PAYMENTS_WITHOUT_PERMISSION = 241,
2796   WEB_BUNDLE_INVALID_NAVIGATION_URL = 242,
2797+  RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS = 254,
2798
2799   // Please add new elements here. The naming convention is abbreviated class
2800   // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
2801diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
2802index 0a7e8fb928..9c2bac10bb 100644
2803--- a/content/browser/blob_storage/blob_url_unittest.cc
2804+++ b/content/browser/blob_storage/blob_url_unittest.cc
2805@@ -182,15 +182,14 @@ class BlobURLTest : public testing::Test {
2806
2807   void TestRequest(const std::string& method,
2808                    const net::HttpRequestHeaders& extra_headers) {
2809-    GURL url("blob:blah");
2810+    auto origin = url::Origin::Create(GURL("https://example.com"));
2811+    auto url = GURL("blob:" + origin.Serialize() + "/id1");
2812     network::ResourceRequest request;
2813     request.url = url;
2814     request.method = method;
2815     request.headers = extra_headers;
2816
2817-    storage::MockBlobRegistryDelegate delegate;
2818-    storage::BlobURLStoreImpl url_store(blob_url_registry_.AsWeakPtr(),
2819-                                        &delegate);
2820+    storage::BlobURLStoreImpl url_store(origin, blob_url_registry_.AsWeakPtr());
2821
2822     mojo::PendingRemote<blink::mojom::Blob> blob_remote;
2823     storage::BlobImpl::Create(
2824diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
2825index 9c39184123..d0073ca0c8 100644
2826--- a/content/browser/browser_child_process_host_impl.cc
2827+++ b/content/browser/browser_child_process_host_impl.cc
2828@@ -672,6 +672,9 @@ void BrowserChildProcessHostImpl::RegisterCoordinatorClient(
2829     mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
2830     mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
2831         client_process) {
2832+  // Intentionally disallow non-browser processes from getting a Coordinator.
2833+  receiver.reset();
2834+
2835   // The child process may have already terminated by the time this message is
2836   // dispatched. We do nothing in that case.
2837   if (!IsProcessLaunched())
2838diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc
2839index 141a96c2ef..8ba6265041 100644
2840--- a/content/browser/browser_interface_binders.cc
2841+++ b/content/browser/browser_interface_binders.cc
2842@@ -377,10 +377,22 @@ void BindTextSuggestionHostForFrame(
2843 }
2844 #endif
2845
2846+// Get the service worker's worker process ID and post a task to bind the
2847+// receiver on a USER_VISIBLE task runner.
2848+// This is necessary because:
2849+// - Binding the host itself and checking the ID on the task's thread may cause
2850+//   a UAF if the host has been deleted in the meantime.
2851+// - The process ID is not yet populated at the time `PopulateInterfaceBinders`
2852+//   is called.
2853 void BindFileUtilitiesHost(
2854-    const ServiceWorkerHost* host,
2855+    ServiceWorkerHost* host,
2856     mojo::PendingReceiver<blink::mojom::FileUtilitiesHost> receiver) {
2857-  FileUtilitiesHostImpl::Create(host->worker_process_id(), std::move(receiver));
2858+  auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
2859+      {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
2860+  task_runner->PostTask(
2861+      FROM_HERE,
2862+      base::BindOnce(&FileUtilitiesHostImpl::Create, host->worker_process_id(),
2863+                     std::move(receiver)));
2864 }
2865
2866 template <typename WorkerHost, typename Interface>
2867@@ -1166,9 +1178,7 @@ void PopulateServiceWorkerBinders(ServiceWorkerHost* host,
2868
2869   // static binders
2870   map->Add<blink::mojom::FileUtilitiesHost>(
2871-      base::BindRepeating(&BindFileUtilitiesHost, host),
2872-      base::ThreadPool::CreateSequencedTaskRunner(
2873-          {base::MayBlock(), base::TaskPriority::USER_VISIBLE}));
2874+      base::BindRepeating(&BindFileUtilitiesHost, host));
2875   map->Add<shape_detection::mojom::BarcodeDetectionProvider>(
2876       base::BindRepeating(&BindBarcodeDetectionProvider));
2877   map->Add<shape_detection::mojom::FaceDetectionProvider>(
2878diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
2879index 634d72af38..c5be9cd6e5 100644
2880--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
2881+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
2882@@ -446,10 +446,10 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
2883     padding = storage::ComputeRandomResponsePadding();
2884   }
2885
2886-  // Note that |has_range_requested| can be safely set to false since it only
2887-  // affects HTTP 206 (Partial) responses, which are blocked from cache storage.
2888-  // See https://fetch.spec.whatwg.org/#main-fetch for usage of
2889-  // |has_range_requested|.
2890+  // While we block most partial responses from being stored, we can have
2891+  // partial responses for bgfetch or opaque responses.
2892+  bool has_range_requested = headers.contains(net::HttpRequestHeaders::kRange);
2893+
2894   return blink::mojom::FetchAPIResponse::New(
2895       url_list, metadata.response().status_code(),
2896       metadata.response().status_text(),
2897@@ -467,7 +467,7 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
2898       static_cast<net::HttpResponseInfo::ConnectionInfo>(
2899           metadata.response().connection_info()),
2900       alpn_negotiated_protocol, metadata.response().was_fetched_via_spdy(),
2901-      /*has_range_requested=*/false, /*auth_challenge_info=*/base::nullopt);
2902+      has_range_requested, /*auth_challenge_info=*/base::nullopt);
2903 }
2904
2905 int64_t CalculateSideDataPadding(
2906@@ -1907,7 +1907,13 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
2907   }
2908
2909   proto::CacheResponse* response_metadata = metadata.mutable_response();
2910-  DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
2911+  if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch &&
2912+      put_context->response->response_type !=
2913+          network::mojom::FetchResponseType::kOpaque &&
2914+      put_context->response->response_type !=
2915+          network::mojom::FetchResponseType::kOpaqueRedirect) {
2916+    DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
2917+  }
2918   response_metadata->set_status_code(put_context->response->status_code);
2919   response_metadata->set_status_text(put_context->response->status_text);
2920   response_metadata->set_response_type(FetchResponseTypeToProtoResponseType(
2921diff --git a/content/browser/child_process_launcher_helper.h b/content/browser/child_process_launcher_helper.h
2922index 532b80efe9..7b78341112 100644
2923--- a/content/browser/child_process_launcher_helper.h
2924+++ b/content/browser/child_process_launcher_helper.h
2925@@ -47,6 +47,10 @@
2926 #include "content/public/common/zygote/zygote_handle.h"  // nogncheck
2927 #endif
2928
2929+#if defined(OS_OHOS)
2930+#include "appmgr/app_mgr_client.h"
2931+#endif
2932+
2933 namespace base {
2934 class CommandLine;
2935 }
2936@@ -252,6 +256,10 @@ class ChildProcessLauncherHelper :
2937 #if defined(OS_FUCHSIA)
2938   std::unique_ptr<sandbox::policy::SandboxPolicyFuchsia> sandbox_policy_;
2939 #endif
2940+
2941+#if defined(OS_OHOS)
2942+  std::unique_ptr<OHOS::AppExecFwk::AppMgrClient> app_mgr_client_{nullptr};
2943+#endif
2944 };
2945
2946 }  // namespace internal
2947diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
2948index 7efc41048b..422d3a0183 100644
2949--- a/content/browser/child_process_launcher_helper_linux.cc
2950+++ b/content/browser/child_process_launcher_helper_linux.cc
2951@@ -99,7 +99,37 @@ ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
2952   }
2953
2954   Process process;
2955+#if defined(OS_OHOS)
2956+  bool for_test = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kForTest);
2957+  if (for_test) {
2958+    process.process = base::LaunchProcess(*command_line(), options);
2959+  } else {
2960+    const std::vector<std::string> argv_str = command_line()->argv();
2961+    std::stringstream argv_ss;
2962+    const char separator = '#';
2963+    for (int i=0; i<argv_str.size()-1; ++i) {
2964+      argv_ss << argv_str[i] << separator;
2965+    }
2966+    argv_ss << argv_str[argv_str.size()-1];
2967+    constexpr int SHARED_FD_INDEX = 0;
2968+    constexpr int IPC_FD_INDEX = 1;
2969+    int32_t shared_fd = options.fds_to_remap[SHARED_FD_INDEX].first;
2970+    int32_t ipc_fd = options.fds_to_remap[IPC_FD_INDEX].first;
2971+    pid_t render_pid = 0;
2972+    if (app_mgr_client_ == nullptr) {
2973+      app_mgr_client_ = std::make_unique<OHOS::AppExecFwk::AppMgrClient>();
2974+    }
2975+    int ret = app_mgr_client_->StartRenderProcess(argv_ss.str(), ipc_fd, shared_fd, render_pid);
2976+    if (ret != 0) {
2977+      LOG(ERROR) << "start render process error, ret=" << ret << ", render pid=" << render_pid;
2978+      process.process = base::Process();
2979+    } else {
2980+      process.process = base::Process(render_pid);
2981+    }
2982+  }
2983+#else
2984   process.process = base::LaunchProcess(*command_line(), options);
2985+#endif
2986   *launch_result = process.process.IsValid() ? LAUNCH_RESULT_SUCCESS
2987                                              : LAUNCH_RESULT_FAILURE;
2988   return process;
2989diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
2990index 3c3fcebab8..fcfe6a0722 100644
2991--- a/content/browser/download/download_browsertest.cc
2992+++ b/content/browser/download/download_browsertest.cc
2993@@ -3596,6 +3596,53 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, UpdateSiteForCookies) {
2994                                 site_a.GetURL("a.test", "/")));
2995 }
2996
2997+// Verifies that isolation info set in DownloadUrlParameters can be populated.
2998+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
2999+                       SiteForCookies_DownloadUrl_IsolationInfoPopulated) {
3000+  // Setup a server that sets cookie.
3001+  net::EmbeddedTestServer site_a;
3002+  base::StringPairs cookie_headers;
3003+  cookie_headers.push_back(std::make_pair(std::string("Set-Cookie"),
3004+                                          std::string("A=lax; SameSite=Lax")));
3005+  cookie_headers.push_back(std::make_pair(
3006+      std::string("Set-Cookie"), std::string("B=strict; SameSite=Strict")));
3007+  site_a.RegisterRequestHandler(CreateBasicResponseHandler(
3008+      "/sets-samesite-cookies", net::HTTP_OK, cookie_headers,
3009+      "application/octet-stream", "abcd"));
3010+  ASSERT_TRUE(site_a.Start());
3011+
3012+  // Download the file.
3013+  SetupEnsureNoPendingDownloads();
3014+  GURL download_url = site_a.GetURL("a.test", "/sets-samesite-cookies");
3015+  std::unique_ptr<download::DownloadUrlParameters> download_parameters(
3016+      DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
3017+          shell()->web_contents(), download_url, TRAFFIC_ANNOTATION_FOR_TESTS));
3018+
3019+  // Mark this request a third party request, cookie should be blocked.
3020+  net::IsolationInfo isolation_info =
3021+      net::IsolationInfo::CreateForInternalRequest(
3022+          url::Origin::Create(GURL("http://www.example.com")));
3023+  download_parameters->set_isolation_info(isolation_info);
3024+
3025+  // Verify the isolation info.
3026+  std::unique_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
3027+  ExpectRequestIsolationInfo(download_url, isolation_info,
3028+                             base::BindLambdaForTesting([&]() {
3029+                               DownloadManagerForShell(shell())->DownloadUrl(
3030+                                   std::move(download_parameters));
3031+                               observer->WaitForFinished();
3032+                             }));
3033+
3034+  // Get the important info from other threads and check it.
3035+  EXPECT_TRUE(EnsureNoPendingDownloads());
3036+
3037+  // Check no cookies are written for URL a.test since it's a third party
3038+  // cookie.
3039+  EXPECT_TRUE(content::GetCookies(shell()->web_contents()->GetBrowserContext(),
3040+                                  download_url)
3041+                  .empty());
3042+}
3043+
3044 // A filename suggestion specified via a @download attribute should not be
3045 // effective if the final download URL is in another origin from the original
3046 // download URL.
3047diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
3048index 69fcf9abbe..0deb3b7c77 100644
3049--- a/content/browser/download/download_manager_impl.h
3050+++ b/content/browser/download/download_manager_impl.h
3051@@ -170,6 +170,11 @@ class CONTENT_EXPORT DownloadManagerImpl
3052       int frame_tree_node_id,
3053       bool from_download_cross_origin_redirect);
3054
3055+  // DownloadItemImplDelegate overrides.
3056+  download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
3057+      override;
3058+  std::string GetApplicationClientIdForFileScanning() const override;
3059+
3060  private:
3061   using DownloadSet = std::set<download::DownloadItem*>;
3062   using DownloadGuidMap =
3063@@ -237,7 +242,6 @@ class CONTENT_EXPORT DownloadManagerImpl
3064   bool ShouldOpenDownload(download::DownloadItemImpl* item,
3065                           ShouldOpenDownloadCallback callback) override;
3066   void CheckForFileRemoval(download::DownloadItemImpl* download_item) override;
3067-  std::string GetApplicationClientIdForFileScanning() const override;
3068   void ResumeInterruptedDownload(
3069       std::unique_ptr<download::DownloadUrlParameters> params,
3070       const GURL& site_url) override;
3071@@ -249,8 +253,6 @@ class CONTENT_EXPORT DownloadManagerImpl
3072   void ReportBytesWasted(download::DownloadItemImpl* download) override;
3073   void BindWakeLockProvider(
3074       mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) override;
3075-  download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
3076-      override;
3077   std::unique_ptr<download::DownloadItemRenameHandler>
3078   GetRenameHandlerForDownload(
3079       download::DownloadItemImpl* download_item) override;
3080diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
3081index 72331e60fc..110f66250e 100644
3082--- a/content/browser/download/save_file.cc
3083+++ b/content/browser/download/save_file.cc
3084@@ -63,10 +63,15 @@ void SaveFile::Finish() {
3085   file_.Finish();
3086 }
3087
3088-void SaveFile::AnnotateWithSourceInformation() {
3089-  // TODO(gbillock): If this method is called, it should set the
3090-  // file_.SetClientGuid() method first.
3091-  NOTREACHED();
3092+void SaveFile::AnnotateWithSourceInformation(
3093+    const std::string& client_guid,
3094+    const GURL& source_url,
3095+    const GURL& referrer_url,
3096+    mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
3097+    download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback) {
3098+  file_.AnnotateWithSourceInformation(client_guid, source_url, referrer_url,
3099+                                      std::move(remote_quarantine),
3100+                                      std::move(on_annotation_done_callback));
3101 }
3102
3103 base::FilePath SaveFile::FullPath() const {
3104diff --git a/content/browser/download/save_file.h b/content/browser/download/save_file.h
3105index 688574b07f..1893a0031f 100644
3106--- a/content/browser/download/save_file.h
3107+++ b/content/browser/download/save_file.h
3108@@ -34,7 +34,12 @@ class SaveFile {
3109   void Detach();
3110   void Cancel();
3111   void Finish();
3112-  void AnnotateWithSourceInformation();
3113+  void AnnotateWithSourceInformation(
3114+      const std::string& client_guid,
3115+      const GURL& source_url,
3116+      const GURL& referrer_url,
3117+      mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
3118+      download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback);
3119   base::FilePath FullPath() const;
3120   bool InProgress() const;
3121   int64_t BytesSoFar() const;
3122diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
3123index 91786d976f..2489b47cf8 100644
3124--- a/content/browser/download/save_file_manager.cc
3125+++ b/content/browser/download/save_file_manager.cc
3126@@ -50,6 +50,7 @@ static SaveFileManager* g_save_file_manager = nullptr;
3127 class SaveFileManager::SimpleURLLoaderHelper
3128     : public network::SimpleURLLoaderStreamConsumer {
3129  public:
3130+  using URLLoaderCompleteCallback = base::OnceCallback<void(bool success)>;
3131   static std::unique_ptr<SimpleURLLoaderHelper> CreateAndStartDownload(
3132       std::unique_ptr<network::ResourceRequest> resource_request,
3133       SaveItemId save_item_id,
3134@@ -58,11 +59,12 @@ class SaveFileManager::SimpleURLLoaderHelper
3135       int render_frame_routing_id,
3136       const net::NetworkTrafficAnnotationTag& annotation_tag,
3137       network::mojom::URLLoaderFactory* url_loader_factory,
3138-      SaveFileManager* save_file_manager) {
3139+      SaveFileManager* save_file_manager,
3140+      URLLoaderCompleteCallback on_complete_cb) {
3141     return std::unique_ptr<SimpleURLLoaderHelper>(new SimpleURLLoaderHelper(
3142         std::move(resource_request), save_item_id, save_package_id,
3143         render_process_id, render_frame_routing_id, annotation_tag,
3144-        url_loader_factory, save_file_manager));
3145+        url_loader_factory, save_file_manager, std::move(on_complete_cb)));
3146   }
3147
3148   ~SimpleURLLoaderHelper() override = default;
3149@@ -76,10 +78,12 @@ class SaveFileManager::SimpleURLLoaderHelper
3150       int render_frame_routing_id,
3151       const net::NetworkTrafficAnnotationTag& annotation_tag,
3152       network::mojom::URLLoaderFactory* url_loader_factory,
3153-      SaveFileManager* save_file_manager)
3154+      SaveFileManager* save_file_manager,
3155+      URLLoaderCompleteCallback on_complete_cb)
3156       : save_file_manager_(save_file_manager),
3157         save_item_id_(save_item_id),
3158-        save_package_id_(save_package_id) {
3159+        save_package_id_(save_package_id),
3160+        on_complete_cb_(std::move(on_complete_cb)) {
3161     GURL url = resource_request->url;
3162     url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
3163                                                    annotation_tag);
3164@@ -124,9 +128,7 @@ class SaveFileManager::SimpleURLLoaderHelper
3165
3166   void OnComplete(bool success) override {
3167     download::GetDownloadTaskRunner()->PostTask(
3168-        FROM_HERE,
3169-        base::BindOnce(&SaveFileManager::SaveFinished, save_file_manager_,
3170-                       save_item_id_, save_package_id_, success));
3171+        FROM_HERE, base::BindOnce(std::move(on_complete_cb_), success));
3172   }
3173
3174   void OnRetry(base::OnceClosure start_retry) override {
3175@@ -138,6 +140,7 @@ class SaveFileManager::SimpleURLLoaderHelper
3176   SaveItemId save_item_id_;
3177   SavePackageId save_package_id_;
3178   std::unique_ptr<network::SimpleURLLoader> url_loader_;
3179+  URLLoaderCompleteCallback on_complete_cb_;
3180
3181   DISALLOW_COPY_AND_ASSIGN(SimpleURLLoaderHelper);
3182 };
3183@@ -188,17 +191,20 @@ SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) {
3184 }
3185
3186 // Call from SavePackage for starting a saving job
3187-void SaveFileManager::SaveURL(SaveItemId save_item_id,
3188-                              const GURL& url,
3189-                              const Referrer& referrer,
3190-                              int render_process_host_id,
3191-                              int render_view_routing_id,
3192-                              int render_frame_routing_id,
3193-                              SaveFileCreateInfo::SaveFileSource save_source,
3194-                              const base::FilePath& file_full_path,
3195-                              BrowserContext* context,
3196-                              StoragePartition* storage_partition,
3197-                              SavePackage* save_package) {
3198+void SaveFileManager::SaveURL(
3199+    SaveItemId save_item_id,
3200+    const GURL& url,
3201+    const Referrer& referrer,
3202+    int render_process_host_id,
3203+    int render_view_routing_id,
3204+    int render_frame_routing_id,
3205+    SaveFileCreateInfo::SaveFileSource save_source,
3206+    const base::FilePath& file_full_path,
3207+    BrowserContext* context,
3208+    StoragePartition* storage_partition,
3209+    SavePackage* save_package,
3210+    const std::string& client_guid,
3211+    mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine) {
3212   DCHECK_CURRENTLY_ON(BrowserThread::UI);
3213
3214   // Insert started saving job to tracking list.
3215@@ -285,11 +291,18 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
3216       factory = storage_partition->GetURLLoaderFactoryForBrowserProcess().get();
3217     }
3218
3219+    base::OnceCallback<void(bool /*success*/)> save_finished_cb =
3220+        base::BindOnce(&SaveFileManager::OnURLLoaderComplete, this,
3221+                       save_item_id, save_package->id(),
3222+                       context->IsOffTheRecord() ? GURL() : url,
3223+                       context->IsOffTheRecord() ? GURL() : referrer.url,
3224+                       client_guid, std::move(remote_quarantine));
3225+
3226     url_loader_helpers_[save_item_id] =
3227         SimpleURLLoaderHelper::CreateAndStartDownload(
3228             std::move(request), save_item_id, save_package->id(),
3229             render_process_host_id, render_frame_routing_id, traffic_annotation,
3230-            factory, this);
3231+            factory, this, std::move(save_finished_cb));
3232   } else {
3233     // We manually start the save job.
3234     auto info = std::make_unique<SaveFileCreateInfo>(
3235@@ -344,6 +357,36 @@ void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
3236       base::BindOnce(&SaveFileManager::CancelSave, this, save_item_id));
3237 }
3238
3239+void SaveFileManager::OnURLLoaderComplete(
3240+    SaveItemId save_item_id,
3241+    SavePackageId save_package_id,
3242+    const GURL& url,
3243+    const GURL& referrer_url,
3244+    const std::string& client_guid,
3245+    mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
3246+    bool is_success) {
3247+  DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
3248+  SaveFile* save_file = LookupSaveFile(save_item_id);
3249+  if (!is_success || !save_file) {
3250+    SaveFinished(save_item_id, save_package_id, is_success);
3251+    return;
3252+  }
3253+
3254+  save_file->AnnotateWithSourceInformation(
3255+      client_guid, url, referrer_url, std::move(remote_quarantine),
3256+      base::BindOnce(&SaveFileManager::OnQuarantineComplete, this, save_item_id,
3257+                     save_package_id));
3258+}
3259+
3260+void SaveFileManager::OnQuarantineComplete(
3261+    SaveItemId save_item_id,
3262+    SavePackageId save_package_id,
3263+    download::DownloadInterruptReason result) {
3264+  DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
3265+  SaveFinished(save_item_id, save_package_id,
3266+               result == download::DOWNLOAD_INTERRUPT_REASON_NONE);
3267+}
3268+
3269 // Notifications sent from the IO thread and run on the file thread:
3270
3271 // The IO thread created |info|, but the file thread (this method) uses it
3272diff --git a/content/browser/download/save_file_manager.h b/content/browser/download/save_file_manager.h
3273index 51eb63a9b1..0d4290b273 100644
3274--- a/content/browser/download/save_file_manager.h
3275+++ b/content/browser/download/save_file_manager.h
3276@@ -61,6 +61,8 @@
3277
3278 #include "base/macros.h"
3279 #include "base/memory/ref_counted.h"
3280+#include "components/download/public/common/download_interrupt_reasons.h"
3281+#include "components/services/quarantine/quarantine.h"
3282 #include "content/browser/download/save_types.h"
3283 #include "content/common/content_export.h"
3284
3285@@ -90,17 +92,20 @@ class CONTENT_EXPORT SaveFileManager
3286
3287   // Saves the specified URL |url|. |save_package| must not be deleted before
3288   // the call to RemoveSaveFile. Should be called on the UI thread,
3289-  void SaveURL(SaveItemId save_item_id,
3290-               const GURL& url,
3291-               const Referrer& referrer,
3292-               int render_process_host_id,
3293-               int render_view_routing_id,
3294-               int render_frame_routing_id,
3295-               SaveFileCreateInfo::SaveFileSource save_source,
3296-               const base::FilePath& file_full_path,
3297-               BrowserContext* context,
3298-               StoragePartition* storage_partition,
3299-               SavePackage* save_package);
3300+  void SaveURL(
3301+      SaveItemId save_item_id,
3302+      const GURL& url,
3303+      const Referrer& referrer,
3304+      int render_process_host_id,
3305+      int render_view_routing_id,
3306+      int render_frame_routing_id,
3307+      SaveFileCreateInfo::SaveFileSource save_source,
3308+      const base::FilePath& file_full_path,
3309+      BrowserContext* context,
3310+      StoragePartition* storage_partition,
3311+      SavePackage* save_package,
3312+      const std::string& client_guid,
3313+      mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine);
3314
3315   // Notifications sent from the IO thread and run on the file thread:
3316   void StartSave(std::unique_ptr<SaveFileCreateInfo> info);
3317@@ -159,6 +164,21 @@ class CONTENT_EXPORT SaveFileManager
3318   // Help function for sending notification of canceling specific request.
3319   void SendCancelRequest(SaveItemId save_item_id);
3320
3321+  // Called on the file thread when the URLLoader completes saving a SaveItem.
3322+  void OnURLLoaderComplete(
3323+      SaveItemId save_item_id,
3324+      SavePackageId save_package_id,
3325+      const GURL& url,
3326+      const GURL& referrer_url,
3327+      const std::string& client_guid,
3328+      mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
3329+      bool is_success);
3330+
3331+  // Called on the file thread when file quarantine finishes on a SaveItem.
3332+  void OnQuarantineComplete(SaveItemId save_item_id,
3333+                            SavePackageId save_package_id,
3334+                            download::DownloadInterruptReason result);
3335+
3336   // Notifications sent from the file thread and run on the UI thread.
3337
3338   // Lookup the SaveManager for this WebContents' saving browser context and
3339diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
3340index 4ceea290dc..5eaed4a726 100644
3341--- a/content/browser/download/save_package.cc
3342+++ b/content/browser/download/save_package.cc
3343@@ -843,6 +843,12 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
3344     RenderFrameHostImpl* requester_frame =
3345         requester_frame_tree_node->current_frame_host();
3346
3347+    mojo::PendingRemote<quarantine::mojom::Quarantine> quarantine;
3348+    auto quarantine_callback =
3349+        download_manager_->GetQuarantineConnectionCallback();
3350+    if (quarantine_callback)
3351+      quarantine_callback.Run(quarantine.InitWithNewPipeAndPassReceiver());
3352+
3353     file_manager_->SaveURL(
3354         save_item_ptr->id(), save_item_ptr->url(), save_item_ptr->referrer(),
3355         requester_frame->GetProcess()->GetID(),
3356@@ -854,7 +860,8 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
3357             ->GetRenderViewHost()
3358             ->GetProcess()
3359             ->GetStoragePartition(),
3360-        this);
3361+        this, download_manager_->GetApplicationClientIdForFileScanning(),
3362+        std::move(quarantine));
3363
3364   } while (process_all_remaining_items && !waiting_item_queue_.empty());
3365 }
3366diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
3367index e58be73ae4..a47eceba37 100644
3368--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
3369+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
3370@@ -448,6 +448,11 @@ void FileSystemAccessManagerImpl::ResolveDefaultDirectory(
3371                   std::move(callback))));
3372 }
3373
3374+void FileSystemAccessManagerImpl::Shutdown() {
3375+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
3376+  permission_context_ = nullptr;
3377+}
3378+
3379 void FileSystemAccessManagerImpl::SetDefaultPathAndShowPicker(
3380     const BindingContext& context,
3381     blink::mojom::FilePickerOptionsPtr options,
3382diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h
3383index 4c9303aa11..e06a3d347f 100644
3384--- a/content/browser/file_system_access/file_system_access_manager_impl.h
3385+++ b/content/browser/file_system_access/file_system_access_manager_impl.h
3386@@ -257,6 +257,8 @@ class CONTENT_EXPORT FileSystemAccessManagerImpl
3387       PathType path_type,
3388       const base::FilePath& path);
3389
3390+  void Shutdown();
3391+
3392  private:
3393   friend class FileSystemAccessFileHandleImpl;
3394
3395diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc
3396index d6ee1e0e10..037345a2f6 100644
3397--- a/content/browser/indexed_db/database_impl.cc
3398+++ b/content/browser/indexed_db/database_impl.cc
3399@@ -87,6 +87,13 @@ void DatabaseImpl::RenameObjectStore(int64_t transaction_id,
3400     return;
3401   }
3402
3403+  if (!transaction->IsAcceptingRequests()) {
3404+    mojo::ReportBadMessage(
3405+        "RenameObjectStore was called after committing or aborting the "
3406+        "transaction");
3407+    return;
3408+  }
3409+
3410   transaction->ScheduleTask(
3411       blink::mojom::IDBTaskType::Preemptive,
3412       BindWeakOperation(&IndexedDBDatabase::RenameObjectStoreOperation,
3413@@ -175,6 +182,12 @@ void DatabaseImpl::Get(int64_t transaction_id,
3414     return;
3415   }
3416
3417+  if (!transaction->IsAcceptingRequests()) {
3418+    mojo::ReportBadMessage(
3419+        "Get was called after committing or aborting the transaction");
3420+    return;
3421+  }
3422+
3423   blink::mojom::IDBDatabase::GetCallback aborting_callback =
3424       CreateCallbackAbortOnDestruct<blink::mojom::IDBDatabase::GetCallback,
3425                                     blink::mojom::IDBDatabaseGetResultPtr>(
3426@@ -225,6 +238,12 @@ void DatabaseImpl::GetAll(int64_t transaction_id,
3427     return;
3428   }
3429
3430+  if (!transaction->IsAcceptingRequests()) {
3431+    mojo::ReportBadMessage(
3432+        "GetAll was called after committing or aborting the transaction");
3433+    return;
3434+  }
3435+
3436   // Hypothetically, this could pass the receiver to the callback immediately.
3437   // However, for result ordering issues, we need to PostTask to mimic
3438   // all of the other operations.
3439@@ -264,6 +283,12 @@ void DatabaseImpl::SetIndexKeys(
3440     return;
3441   }
3442
3443+  if (!transaction->IsAcceptingRequests()) {
3444+    mojo::ReportBadMessage(
3445+        "SetIndexKeys was called after committing or aborting the transaction");
3446+    return;
3447+  }
3448+
3449   transaction->ScheduleTask(
3450       blink::mojom::IDBTaskType::Preemptive,
3451       BindWeakOperation(&IndexedDBDatabase::SetIndexKeysOperation,
3452@@ -290,6 +315,13 @@ void DatabaseImpl::SetIndexesReady(int64_t transaction_id,
3453     return;
3454   }
3455
3456+  if (!transaction->IsAcceptingRequests()) {
3457+    mojo::ReportBadMessage(
3458+        "SetIndexesReady was called after committing or aborting the "
3459+        "transaction");
3460+    return;
3461+  }
3462+
3463   transaction->ScheduleTask(
3464       blink::mojom::IDBTaskType::Preemptive,
3465       BindWeakOperation(&IndexedDBDatabase::SetIndexesReadyOperation,
3466@@ -327,6 +359,12 @@ void DatabaseImpl::OpenCursor(
3467     return;
3468   }
3469
3470+  if (!transaction->IsAcceptingRequests()) {
3471+    mojo::ReportBadMessage(
3472+        "OpenCursor was called after committing or aborting the transaction");
3473+    return;
3474+  }
3475+
3476   blink::mojom::IDBDatabase::OpenCursorCallback aborting_callback =
3477       CreateCallbackAbortOnDestruct<
3478           blink::mojom::IDBDatabase::OpenCursorCallback,
3479@@ -376,6 +414,12 @@ void DatabaseImpl::Count(
3480   if (!transaction)
3481     return;
3482
3483+  if (!transaction->IsAcceptingRequests()) {
3484+    mojo::ReportBadMessage(
3485+        "Count was called after committing or aborting the transaction");
3486+    return;
3487+  }
3488+
3489   transaction->ScheduleTask(BindWeakOperation(
3490       &IndexedDBDatabase::CountOperation, connection_->database()->AsWeakPtr(),
3491       object_store_id, index_id,
3492@@ -401,6 +445,12 @@ void DatabaseImpl::DeleteRange(
3493   if (!transaction)
3494     return;
3495
3496+  if (!transaction->IsAcceptingRequests()) {
3497+    mojo::ReportBadMessage(
3498+        "DeleteRange was called after committing or aborting the transaction");
3499+    return;
3500+  }
3501+
3502   transaction->ScheduleTask(BindWeakOperation(
3503       &IndexedDBDatabase::DeleteRangeOperation,
3504       connection_->database()->AsWeakPtr(), object_store_id,
3505@@ -424,6 +474,13 @@ void DatabaseImpl::GetKeyGeneratorCurrentNumber(
3506   if (!transaction)
3507     return;
3508
3509+  if (!transaction->IsAcceptingRequests()) {
3510+    mojo::ReportBadMessage(
3511+        "GetKeyGeneratorCurrentNumber was called after committing or aborting "
3512+        "the transaction");
3513+    return;
3514+  }
3515+
3516   transaction->ScheduleTask(BindWeakOperation(
3517       &IndexedDBDatabase::GetKeyGeneratorCurrentNumberOperation,
3518       connection_->database()->AsWeakPtr(), object_store_id,
3519@@ -447,6 +504,12 @@ void DatabaseImpl::Clear(
3520   if (!transaction)
3521     return;
3522
3523+  if (!transaction->IsAcceptingRequests()) {
3524+    mojo::ReportBadMessage(
3525+        "Clear was called after committing or aborting the transaction");
3526+    return;
3527+  }
3528+
3529   transaction->ScheduleTask(BindWeakOperation(
3530       &IndexedDBDatabase::ClearOperation, connection_->database()->AsWeakPtr(),
3531       object_store_id, std::move(callbacks)));
3532@@ -474,6 +537,12 @@ void DatabaseImpl::CreateIndex(int64_t transaction_id,
3533     return;
3534   }
3535
3536+  if (!transaction->IsAcceptingRequests()) {
3537+    mojo::ReportBadMessage(
3538+        "CreateIndex was called after committing or aborting the transaction");
3539+    return;
3540+  }
3541+
3542   transaction->ScheduleTask(
3543       blink::mojom::IDBTaskType::Preemptive,
3544       BindWeakOperation(&IndexedDBDatabase::CreateIndexOperation,
3545@@ -499,6 +568,12 @@ void DatabaseImpl::DeleteIndex(int64_t transaction_id,
3546     return;
3547   }
3548
3549+  if (!transaction->IsAcceptingRequests()) {
3550+    mojo::ReportBadMessage(
3551+        "DeleteIndex was called after committing or aborting the transaction");
3552+    return;
3553+  }
3554+
3555   transaction->ScheduleTask(BindWeakOperation(
3556       &IndexedDBDatabase::DeleteIndexOperation,
3557       connection_->database()->AsWeakPtr(), object_store_id, index_id));
3558@@ -523,6 +598,12 @@ void DatabaseImpl::RenameIndex(int64_t transaction_id,
3559     return;
3560   }
3561
3562+  if (!transaction->IsAcceptingRequests()) {
3563+    mojo::ReportBadMessage(
3564+        "RenameIndex was called after committing or aborting the transaction");
3565+    return;
3566+  }
3567+
3568   transaction->ScheduleTask(
3569       BindWeakOperation(&IndexedDBDatabase::RenameIndexOperation,
3570                         connection_->database()->AsWeakPtr(), object_store_id,
3571diff --git a/content/browser/indexed_db/indexed_db_transaction.h b/content/browser/indexed_db/indexed_db_transaction.h
3572index 6acdd5db56..7536d35f00 100644
3573--- a/content/browser/indexed_db/indexed_db_transaction.h
3574+++ b/content/browser/indexed_db/indexed_db_transaction.h
3575@@ -67,6 +67,14 @@ class CONTENT_EXPORT IndexedDBTransaction {
3576   // Signals the transaction for commit.
3577   void SetCommitFlag();
3578
3579+  // Returns false if the transaction has been signalled to commit, is in the
3580+  // process of committing, or finished committing or was aborted. Essentially
3581+  // when this returns false no tasks should be scheduled that try to modify
3582+  // the transaction.
3583+  bool IsAcceptingRequests() {
3584+    return !is_commit_pending_ && state_ != COMMITTING && state_ != FINISHED;
3585+  }
3586+
3587   // This transaction is ultimately backed by a LevelDBScope. Aborting a
3588   // transaction rolls back the LevelDBScopes, which (if LevelDBScopes is in
3589   // single-sequence mode) can fail. This returns the result of that rollback,
3590diff --git a/content/browser/indexed_db/transaction_impl.cc b/content/browser/indexed_db/transaction_impl.cc
3591index 1abde1c784..b0b19dd059 100644
3592--- a/content/browser/indexed_db/transaction_impl.cc
3593+++ b/content/browser/indexed_db/transaction_impl.cc
3594@@ -57,6 +57,13 @@ void TransactionImpl::CreateObjectStore(int64_t object_store_id,
3595     return;
3596   }
3597
3598+  if (!transaction_->IsAcceptingRequests()) {
3599+    mojo::ReportBadMessage(
3600+        "CreateObjectStore was called after committing or aborting the "
3601+        "transaction");
3602+    return;
3603+  }
3604+
3605   IndexedDBConnection* connection = transaction_->connection();
3606   if (!connection->IsConnected())
3607     return;
3608@@ -79,6 +86,13 @@ void TransactionImpl::DeleteObjectStore(int64_t object_store_id) {
3609     return;
3610   }
3611
3612+  if (!transaction_->IsAcceptingRequests()) {
3613+    mojo::ReportBadMessage(
3614+        "DeleteObjectStore was called after committing or aborting the "
3615+        "transaction");
3616+    return;
3617+  }
3618+
3619   IndexedDBConnection* connection = transaction_->connection();
3620   if (!connection->IsConnected())
3621     return;
3622@@ -111,6 +125,12 @@ void TransactionImpl::Put(
3623     return;
3624   }
3625
3626+  if (!transaction_->IsAcceptingRequests()) {
3627+    mojo::ReportBadMessage(
3628+        "Put was called after committing or aborting the transaction");
3629+    return;
3630+  }
3631+
3632   IndexedDBConnection* connection = transaction_->connection();
3633   if (!connection->IsConnected()) {
3634     IndexedDBDatabaseError error(blink::mojom::IDBException::kUnknownError,
3635@@ -170,6 +190,12 @@ void TransactionImpl::PutAll(int64_t object_store_id,
3636     return;
3637   }
3638
3639+  if (!transaction_->IsAcceptingRequests()) {
3640+    mojo::ReportBadMessage(
3641+        "PutAll was called after committing or aborting the transaction");
3642+    return;
3643+  }
3644+
3645   std::vector<std::vector<IndexedDBExternalObject>> external_objects_per_put(
3646       puts.size());
3647   for (size_t i = 0; i < puts.size(); i++) {
3648@@ -268,6 +294,12 @@ void TransactionImpl::Commit(int64_t num_errors_handled) {
3649   if (!transaction_)
3650     return;
3651
3652+  if (!transaction_->IsAcceptingRequests()) {
3653+    // This really shouldn't be happening, but seems to be happening anyway. So
3654+    // rather than killing the renderer, simply ignore the request.
3655+    return;
3656+  }
3657+
3658   IndexedDBConnection* connection = transaction_->connection();
3659   if (!connection->IsConnected())
3660     return;
3661diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
3662index 6b1bdfa3fd..552a9cfe82 100644
3663--- a/content/browser/loader/navigation_url_loader_impl.cc
3664+++ b/content/browser/loader/navigation_url_loader_impl.cc
3665@@ -620,6 +620,13 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
3666     if (known_schemes_.find(resource_request_->url.scheme()) ==
3667         known_schemes_.end()) {
3668       mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
3669+      base::Optional<url::Origin> initiating_origin;
3670+      if (url_chain_.size() > 1) {
3671+        initiating_origin =
3672+            url::Origin::Create(url_chain_[url_chain_.size() - 2]);
3673+      } else {
3674+        initiating_origin = resource_request_->request_initiator;
3675+      }
3676       bool handled = GetContentClient()->browser()->HandleExternalProtocol(
3677           resource_request_->url, web_contents_getter_,
3678           ChildProcessHost::kInvalidUniqueID, frame_tree_node_id_,
3679@@ -628,7 +635,7 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
3680               static_cast<int>(blink::mojom::ResourceType::kMainFrame),
3681           static_cast<ui::PageTransition>(resource_request_->transition_type),
3682           resource_request_->has_user_gesture,
3683-          resource_request_->request_initiator, &loader_factory);
3684+          initiating_origin, &loader_factory);
3685
3686       if (!handled) {
3687         handled = GetContentClient()->browser()->HandleExternalProtocol(
3688diff --git a/content/browser/media/ohos/ohos_media_player_renderer.cc b/content/browser/media/ohos/ohos_media_player_renderer.cc
3689index 69bbd72e2f..54db096c88 100644
3690--- a/content/browser/media/ohos/ohos_media_player_renderer.cc
3691+++ b/content/browser/media/ohos/ohos_media_player_renderer.cc
3692@@ -123,15 +123,21 @@ void OHOSMediaPlayerRenderer::FinishPaint(int32_t fd) {
3693
3694 void OHOSMediaPlayerRenderer::OnFrameAvailable(int fd,
3695                                                uint32_t size,
3696-                                               int32_t width,
3697-                                               int32_t height) {
3698+                                               int32_t coded_width,
3699+                                               int32_t coded_height,
3700+                                               int32_t visible_width,
3701+                                               int32_t visible_height,
3702+                                               int32_t format) {
3703   if (client_extension_) {
3704     auto ohos_buffer = media::mojom::OhosSurfaceBufferHandle::New();
3705     ohos_buffer->buffer_size = size;
3706     base::ScopedFD buffer_fd(dup(fd));
3707     ohos_buffer->fd_browser = fd;
3708-    ohos_buffer->width = width;
3709-    ohos_buffer->height = height;
3710+    ohos_buffer->coded_width = coded_width;
3711+    ohos_buffer->coded_height = coded_height;
3712+    ohos_buffer->visible_width = visible_width;
3713+    ohos_buffer->visible_height = visible_height;
3714+    ohos_buffer->format = format;
3715     ohos_buffer->buffer_fd = mojo::PlatformHandle(std::move(buffer_fd));
3716     client_extension_->OnFrameUpdate(std::move(ohos_buffer));
3717   }
3718diff --git a/content/browser/media/ohos/ohos_media_player_renderer.h b/content/browser/media/ohos/ohos_media_player_renderer.h
3719index 38c5d0c224..21753d6ccd 100644
3720--- a/content/browser/media/ohos/ohos_media_player_renderer.h
3721+++ b/content/browser/media/ohos/ohos_media_player_renderer.h
3722@@ -58,8 +58,11 @@ class CONTENT_EXPORT OHOSMediaPlayerRenderer
3723   // media::OHOSMediaPlayerBridge::Client implementation
3724   void OnFrameAvailable(int fd,
3725                         uint32_t size,
3726-                        int32_t width,
3727-                        int32_t height) override;
3728+                        int32_t coded_width,
3729+                        int32_t coded_height,
3730+                        int32_t visible_width,
3731+                        int32_t visible_height,
3732+                        int32_t format) override;
3733   void OnMediaDurationChanged(base::TimeDelta duration) override;
3734   void OnPlaybackComplete() override;
3735   void OnError(int error) override;
3736diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
3737index b0b02bf700..2a9ce12ff0 100644
3738--- a/content/browser/renderer_host/frame_tree_node.cc
3739+++ b/content/browser/renderer_host/frame_tree_node.cc
3740@@ -475,6 +475,12 @@ bool FrameTreeNode::HasPendingCrossDocumentNavigation() const {
3741
3742 bool FrameTreeNode::CommitFramePolicy(
3743     const blink::FramePolicy& new_frame_policy) {
3744+  // Documents create iframes, iframes host new documents. Both are associated
3745+  // with sandbox flags. They are required to be stricter or equal to their
3746+  // owner when they change, as we go down.
3747+  // TODO(https://crbug.com/1262061). Enforce the invariant mentioned above,
3748+  // once the interactions with FencedIframe has been tested and clarified.
3749+
3750   bool did_change_flags = new_frame_policy.sandbox_flags !=
3751                           replication_state_->frame_policy.sandbox_flags;
3752   bool did_change_container_policy =
3753diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
3754index f86413d26f..7bca1e9446 100644
3755--- a/content/browser/renderer_host/render_frame_host_impl.cc
3756+++ b/content/browser/renderer_host/render_frame_host_impl.cc
3757@@ -826,9 +826,11 @@ enum class VerifyDidCommitParamsDifference {
3758 };
3759
3760 bool ValidateCSPAttribute(const std::string& value) {
3761+  static const size_t kMaxLengthCSPAttribute = 4096;
3762   if (!base::IsStringASCII(value))
3763     return false;
3764-  if (value.find('\n') != std::string::npos ||
3765+  if (value.length() > kMaxLengthCSPAttribute ||
3766+      value.find('\n') != std::string::npos ||
3767       value.find('\r') != std::string::npos) {
3768     return false;
3769   }
3770@@ -2781,6 +2783,16 @@ void RenderFrameHostImpl::CreateChildFrame(
3771     return;
3772   }
3773
3774+  // Documents create iframes, iframes host new documents. Both are associated
3775+  // with sandbox flags. They are required to be stricter or equal to their
3776+  // owner when they are created, as we go down.
3777+  if (frame_policy.sandbox_flags !=
3778+      (frame_policy.sandbox_flags | active_sandbox_flags())) {
3779+    bad_message::ReceivedBadMessage(
3780+        GetProcess(), bad_message::RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS);
3781+    return;
3782+  }
3783+
3784   // TODO(crbug.com/1145708). The interface exposed to tests should
3785   // match the mojo interface.
3786   OnCreateChildFrame(new_routing_id, std::move(frame_remote),
3787diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
3788index d186f75e51..f0e8942562 100644
3789--- a/content/browser/renderer_host/render_process_host_impl.cc
3790+++ b/content/browser/renderer_host/render_process_host_impl.cc
3791@@ -2581,6 +2581,9 @@ void RenderProcessHostImpl::RegisterCoordinatorClient(
3792     mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
3793     mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
3794         client_process) {
3795+  // Intentionally disallow non-browser processes from getting a Coordinator.
3796+  receiver.reset();
3797+
3798   if (!GetProcess().IsValid()) {
3799     // If the process dies before we get this message. we have no valid PID
3800     // and there's nothing to register.
3801@@ -3341,6 +3344,9 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
3802 #endif
3803 #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
3804     switches::kSchedulerBoostUrgent,
3805+#endif
3806+#if defined(OS_OHOS)
3807+    switches::kForTest,
3808 #endif
3809   };
3810   renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
3811diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
3812index 2ff6de6333..cfef02b3a1 100644
3813--- a/content/browser/security_exploit_browsertest.cc
3814+++ b/content/browser/security_exploit_browsertest.cc
3815@@ -680,7 +680,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
3816   // If the process is killed, this test passes.
3817   EXPECT_EQ(
3818       "Received bad user message: "
3819-      "Non committable URL passed to BlobURLStore::Register",
3820+      "URL with invalid origin passed to BlobURLStore::Register",
3821       crash_observer.Wait());
3822 }
3823
3824diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
3825index 99753b0b4b..c0c6f1ecaf 100644
3826--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
3827+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
3828@@ -449,8 +449,10 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
3829   // NetworkService.
3830   URLLoaderAssets(
3831       scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
3832+      mojo::PendingRemote<network::mojom::URLLoader> url_loader,
3833       std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
3834       : shared_url_loader_factory_(std::move(shared_url_loader_factory)),
3835+        url_loader_(std::move(url_loader)),
3836         url_loader_client_(std::move(url_loader_client)) {}
3837
3838   void MaybeReportToDevTools(std::pair<int, int> worker_id,
3839@@ -467,6 +469,7 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
3840
3841   // NetworkService:
3842   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
3843+  mojo::PendingRemote<network::mojom::URLLoader> url_loader_;
3844
3845   // Both:
3846   std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_;
3847@@ -625,7 +628,8 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
3848   auto params = blink::mojom::DispatchFetchEventParams::New();
3849   params->request = std::move(request_);
3850   params->client_id = client_id_;
3851-  params->preload_handle = std::move(preload_handle_);
3852+  params->preload_url_loader_client_receiver =
3853+      std::move(preload_url_loader_client_receiver_);
3854   params->is_offline_capability_check = is_offline_capability_check_;
3855
3856   // TODO(https://crbug.com/900700): Make the remote connected to a receiver
3857@@ -710,13 +714,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
3858   // When the fetch event is for an offline capability check, respond to the
3859   // navigation preload with a network disconnected error, to simulate offline.
3860   if (is_offline_capability_check_) {
3861-    mojo::PendingRemote<network::mojom::URLLoader> url_loader_to_pass;
3862     mojo::Remote<network::mojom::URLLoaderClient> url_loader_client;
3863-    auto dummy_receiver = url_loader_to_pass.InitWithNewPipeAndPassReceiver();
3864
3865-    preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
3866-    preload_handle_->url_loader = std::move(url_loader_to_pass);
3867-    preload_handle_->url_loader_client_receiver =
3868+    preload_url_loader_client_receiver_ =
3869         url_loader_client.BindNewPipeAndPassReceiver();
3870
3871     url_loader_client->OnComplete(
3872@@ -755,12 +755,10 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
3873   factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
3874       std::move(network_factory));
3875
3876-  preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
3877-
3878   // Create the DelegatingURLLoaderClient, which becomes the
3879   // URLLoaderClient for the navigation preload network request.
3880   mojo::PendingRemote<network::mojom::URLLoaderClient> inner_url_loader_client;
3881-  preload_handle_->url_loader_client_receiver =
3882+  preload_url_loader_client_receiver_ =
3883       inner_url_loader_client.InitWithNewPipeAndPassReceiver();
3884   auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
3885       std::move(inner_url_loader_client), resource_request);
3886@@ -795,11 +793,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
3887       net::MutableNetworkTrafficAnnotationTag(
3888           kNavigationPreloadTrafficAnnotation));
3889
3890-  preload_handle_->url_loader = std::move(url_loader);
3891-
3892   DCHECK(!url_loader_assets_);
3893   url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
3894-      std::move(factory), std::move(url_loader_client));
3895+      std::move(factory), std::move(url_loader), std::move(url_loader_client));
3896   return true;
3897 }
3898
3899diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
3900index d436dbfba3..056b1ec439 100644
3901--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
3902+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
3903@@ -123,10 +123,11 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
3904
3905   scoped_refptr<URLLoaderAssets> url_loader_assets_;
3906
3907-  // |preload_handle_| holds the URLLoader and URLLoaderClient for the service
3908-  // worker to receive the navigation preload response. It's passed to the
3909-  // service worker along with the fetch event.
3910-  blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
3911+  // Holds the URLLoaderClient for the service worker to receive the navigation
3912+  // preload response. It's passed to the service worker along with the fetch
3913+  // event.
3914+  mojo::PendingReceiver<network::mojom::URLLoaderClient>
3915+      preload_url_loader_client_receiver_;
3916
3917   // Whether to dispatch an offline-capability-check fetch event.
3918   const bool is_offline_capability_check_ = false;
3919diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
3920index 65c4f1049f..7a517fe224 100644
3921--- a/content/browser/storage_partition_impl.cc
3922+++ b/content/browser/storage_partition_impl.cc
3923@@ -1064,6 +1064,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
3924                                   GetDatabaseTracker()));
3925   }
3926
3927+  if (GetFileSystemAccessManager())
3928+    GetFileSystemAccessManager()->Shutdown();
3929+
3930   if (GetFileSystemContext())
3931     GetFileSystemContext()->Shutdown();
3932
3933diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
3934index 3e19bacca3..e3a9179342 100644
3935--- a/content/browser/web_contents/web_contents_impl.cc
3936+++ b/content/browser/web_contents/web_contents_impl.cc
3937@@ -2586,7 +2586,7 @@ void WebContentsImpl::SetSlowWebPreferences(
3938     // Otherwise default is disabled.
3939     std::string touch_enabled_default_switch =
3940         switches::kTouchEventFeatureDetectionDisabled;
3941-#if defined(OS_ANDROID)
3942+#if defined(OS_ANDROID) || defined(OS_OHOS)
3943     touch_enabled_default_switch = switches::kTouchEventFeatureDetectionEnabled;
3944 #endif  // defined(OS_ANDROID)
3945     const std::string touch_enabled_switch =
3946diff --git a/content/browser/webauth/authenticator_common.cc b/content/browser/webauth/authenticator_common.cc
3947index 069543a490..16d3a019fa 100644
3948--- a/content/browser/webauth/authenticator_common.cc
3949+++ b/content/browser/webauth/authenticator_common.cc
3950@@ -894,6 +894,13 @@ void AuthenticatorCommon::MakeCredential(
3951     return;
3952   }
3953
3954+  if (!security_checker_->DeduplicateCredentialDescriptorListAndValidateLength(
3955+          &options->exclude_credentials)) {
3956+    mojo::ReportBadMessage("invalid exclude_credentials length");
3957+    InvokeCallbackAndCleanup(std::move(callback), blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
3958+    return;
3959+  }
3960+
3961   request_delegate_ = CreateRequestDelegate();
3962   if (!request_delegate_) {
3963     InvokeCallbackAndCleanup(std::move(callback),
3964@@ -1155,6 +1162,13 @@ void AuthenticatorCommon::GetAssertion(
3965     return;
3966   }
3967
3968+  if (!security_checker_->DeduplicateCredentialDescriptorListAndValidateLength(
3969+          &options->allow_credentials)) {
3970+    mojo::ReportBadMessage("invalid allow_credentials length");
3971+    InvokeCallbackAndCleanup(std::move(callback), blink::mojom::AuthenticatorStatus::NOT_ALLOWED_ERROR);
3972+    return;
3973+  }
3974+
3975   request_delegate_ = CreateRequestDelegate();
3976   if (!request_delegate_) {
3977     InvokeCallbackAndCleanup(std::move(callback),
3978diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
3979index 333d020662..fd43d3902d 100644
3980--- a/content/browser/webauth/authenticator_impl_unittest.cc
3981+++ b/content/browser/webauth/authenticator_impl_unittest.cc
3982@@ -67,6 +67,7 @@
3983 #include "device/fido/multiple_virtual_fido_device_factory.h"
3984 #include "device/fido/pin.h"
3985 #include "device/fido/public_key.h"
3986+#include "device/fido/public_key_credential_descriptor.h"
3987 #include "device/fido/test_callback_receiver.h"
3988 #include "device/fido/virtual_fido_device.h"
3989 #include "device/fido/virtual_fido_device_factory.h"
3990@@ -459,6 +460,9 @@ class AuthenticatorTestBase : public content::RenderViewHostTestHarness {
3991   void SetUp() override {
3992     content::RenderViewHostTestHarness::SetUp();
3993
3994+    mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
3995+        &AuthenticatorTestBase::OnMojoError, base::Unretained(this)));
3996+
3997 #if BUILDFLAG(IS_CHROMEOS_ASH)
3998     chromeos::U2FClient::InitializeFake();
3999 #endif
4000@@ -469,6 +473,8 @@ class AuthenticatorTestBase : public content::RenderViewHostTestHarness {
4001   void TearDown() override {
4002     content::RenderViewHostTestHarness::TearDown();
4003
4004+  mojo::SetDefaultProcessErrorHandler(base::NullCallback());
4005+
4006 #if BUILDFLAG(IS_CHROMEOS_ASH)
4007     chromeos::U2FClient::Shutdown();
4008 #endif
4009@@ -483,7 +489,23 @@ class AuthenticatorTestBase : public content::RenderViewHostTestHarness {
4010             std::move(virtual_device_factory));
4011   }
4012
4013+  void SetMojoErrorHandler(
4014+      base::RepeatingCallback<void(const std::string&)> callback) {
4015+    mojo_error_handler_ = callback;
4016+  }
4017+
4018   device::test::VirtualFidoDeviceFactory* virtual_device_factory_;
4019+
4020+ private:
4021+  void OnMojoError(const std::string& error) {
4022+    if (mojo_error_handler_) {
4023+      mojo_error_handler_.Run(error);
4024+      return;
4025+    }
4026+    FAIL() << "Unhandled mojo error: " << error;
4027+  }
4028+
4029+  base::RepeatingCallback<void(const std::string&)> mojo_error_handler_;
4030 };
4031
4032 class AuthenticatorImplTest : public AuthenticatorTestBase {
4033@@ -632,18 +654,17 @@ class AuthenticatorImplTest : public AuthenticatorTestBase {
4034     scoped_feature_list_->InitAndDisableFeature(feature);
4035   }
4036
4037- protected:
4038+  scoped_refptr<::testing::NiceMock<device::MockBluetoothAdapter>>
4039+      mock_adapter_ = base::MakeRefCounted<
4040+          ::testing::NiceMock<device::MockBluetoothAdapter>>();
4041+
4042+ private:
4043   std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
4044   base::Optional<base::test::ScopedFeatureList> scoped_feature_list_;
4045   std::unique_ptr<device::BluetoothAdapterFactory::GlobalValuesForTesting>
4046       bluetooth_global_values_ =
4047           device::BluetoothAdapterFactory::Get()->InitGlobalValuesForTesting();
4048-  scoped_refptr<::testing::NiceMock<device::MockBluetoothAdapter>>
4049-      mock_adapter_ = base::MakeRefCounted<
4050-          ::testing::NiceMock<device::MockBluetoothAdapter>>();
4051   data_decoder::test::InProcessDataDecoder data_decoder_service_;
4052-
4053- private:
4054   url::ScopedSchemeRegistryForTests scoped_registry_;
4055 };
4056
4057@@ -3523,7 +3544,7 @@ TEST_F(AuthenticatorImplTest, AllowListWithOnlyOversizedCredentialIds) {
4058
4059   for (const bool has_app_id : {false, true}) {
4060     SCOPED_TRACE(has_app_id);
4061-    virtual_device_factory_->mutable_state()->allow_list_sizes.clear();
4062+    virtual_device_factory_->mutable_state()->allow_list_history.clear();
4063
4064     PublicKeyCredentialRequestOptionsPtr options =
4065         GetTestPublicKeyCredentialRequestOptions();
4066@@ -3535,14 +3556,200 @@ TEST_F(AuthenticatorImplTest, AllowListWithOnlyOversizedCredentialIds) {
4067
4068     EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
4069               AuthenticatorStatus::NOT_ALLOWED_ERROR);
4070-    const auto& allow_list_sizes =
4071-        virtual_device_factory_->mutable_state()->allow_list_sizes;
4072+    const auto& allow_list_history =
4073+        virtual_device_factory_->mutable_state()->allow_list_history;
4074     // No empty allow-list requests should have been made.
4075-    EXPECT_TRUE(std::none_of(allow_list_sizes.cbegin(), allow_list_sizes.cend(),
4076-                             [](size_t size) { return size == 0; }));
4077+    EXPECT_TRUE(std::none_of(
4078+        allow_list_history.cbegin(), allow_list_history.cend(),
4079+        [](const std::vector<device::PublicKeyCredentialDescriptor>&
4080+               allow_list) { return allow_list.empty(); }));
4081   }
4082 }
4083
4084+// Tests that duplicate credential IDs are filtered from an assertion allow_list
4085+// parameter.
4086+TEST_F(AuthenticatorImplTest, AllowListWithDuplicateCredentialIds) {
4087+  NavigateAndCommit(GURL(kTestOrigin1));
4088+
4089+  device::VirtualCtap2Device::Config config;
4090+  config.u2f_support = true;
4091+  config.max_credential_id_length = kTestCredentialIdLength;
4092+  config.max_credential_count_in_list = 10;
4093+  virtual_device_factory_->SetCtap2Config(config);
4094+
4095+  device::PublicKeyCredentialDescriptor cred_a(
4096+      device::CredentialType::kPublicKey,
4097+      std::vector<uint8_t>(kTestCredentialIdLength, 1), {});
4098+  device::PublicKeyCredentialDescriptor cred_b(
4099+      device::CredentialType::kPublicKey,
4100+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4101+      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
4102+  // Same ID as `cred_a` and `cred_b` but with different transports.
4103+  device::PublicKeyCredentialDescriptor cred_c(
4104+      device::CredentialType::kPublicKey,
4105+      std::vector<uint8_t>(kTestCredentialIdLength, 1),
4106+      {device::FidoTransportProtocol::kBluetoothLowEnergy});
4107+  device::PublicKeyCredentialDescriptor cred_d(
4108+      device::CredentialType::kPublicKey,
4109+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4110+      {device::FidoTransportProtocol::kBluetoothLowEnergy});
4111+
4112+  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
4113+      cred_b.id(), kTestRelyingPartyId));
4114+
4115+  PublicKeyCredentialRequestOptionsPtr options =
4116+      GetTestPublicKeyCredentialRequestOptions();
4117+  options->allow_credentials.clear();
4118+  options->allow_credentials.insert(options->allow_credentials.end(), 5,
4119+                                    cred_a);
4120+  options->allow_credentials.push_back(cred_b);
4121+  options->allow_credentials.insert(options->allow_credentials.end(), 3,
4122+                                    cred_c);
4123+  options->allow_credentials.insert(options->allow_credentials.end(), 2,
4124+                                    cred_d);
4125+
4126+  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
4127+            AuthenticatorStatus::SUCCESS);
4128+  EXPECT_EQ(virtual_device_factory_->mutable_state()->allow_list_history.size(),
4129+            1u);
4130+  // Transport hints from descriptors with equal IDs should be merged.
4131+  device::PublicKeyCredentialDescriptor cred_a_and_c(
4132+      device::CredentialType::kPublicKey,
4133+      std::vector<uint8_t>(kTestCredentialIdLength, 1),
4134+      // The union of the empty transports in `cred_a` plus the non-empty set
4135+      // from `cred_c` should still be empty, since empty set is interpreted to
4136+      // mean "any available transport".
4137+      {});
4138+  device::PublicKeyCredentialDescriptor cred_b_and_d(
4139+      device::CredentialType::kPublicKey,
4140+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4141+      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
4142+       device::FidoTransportProtocol::kBluetoothLowEnergy});
4143+  EXPECT_THAT(
4144+      virtual_device_factory_->mutable_state()->allow_list_history.at(0),
4145+      testing::UnorderedElementsAre(cred_a_and_c, cred_b_and_d));
4146+}
4147+
4148+// Tests that duplicate credential IDs are filtered from a registration
4149+// exclude_list parameter.
4150+TEST_F(AuthenticatorImplTest, ExcludeListWithDuplicateCredentialIds) {
4151+  NavigateAndCommit(GURL(kTestOrigin1));
4152+
4153+  device::VirtualCtap2Device::Config config;
4154+  config.u2f_support = true;
4155+  config.max_credential_id_length = kTestCredentialIdLength;
4156+  config.max_credential_count_in_list = 100;
4157+  virtual_device_factory_->SetCtap2Config(config);
4158+
4159+  device::PublicKeyCredentialDescriptor cred_a(
4160+      device::CredentialType::kPublicKey,
4161+      std::vector<uint8_t>(kTestCredentialIdLength, 1), {});
4162+  device::PublicKeyCredentialDescriptor cred_b(
4163+      device::CredentialType::kPublicKey,
4164+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4165+      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
4166+  // Same ID as `cred_a` and `cred_b` but with different transports.
4167+  device::PublicKeyCredentialDescriptor cred_c(
4168+      device::CredentialType::kPublicKey,
4169+      std::vector<uint8_t>(kTestCredentialIdLength, 1),
4170+      {device::FidoTransportProtocol::kBluetoothLowEnergy});
4171+  device::PublicKeyCredentialDescriptor cred_d(
4172+      device::CredentialType::kPublicKey,
4173+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4174+      {device::FidoTransportProtocol::kBluetoothLowEnergy});
4175+
4176+  PublicKeyCredentialCreationOptionsPtr options =
4177+      GetTestPublicKeyCredentialCreationOptions();
4178+  options->exclude_credentials.clear();
4179+  options->exclude_credentials.insert(options->exclude_credentials.end(), 5,
4180+                                      cred_a);
4181+  options->exclude_credentials.push_back(cred_b);
4182+  options->exclude_credentials.insert(options->exclude_credentials.end(), 3,
4183+                                      cred_c);
4184+  options->exclude_credentials.insert(options->exclude_credentials.end(), 2,
4185+                                      cred_d);
4186+
4187+  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
4188+            AuthenticatorStatus::SUCCESS);
4189+  EXPECT_EQ(
4190+      virtual_device_factory_->mutable_state()->exclude_list_history.size(),
4191+      1u);
4192+  // Transport hints from descriptors with equal IDs should be merged.
4193+  device::PublicKeyCredentialDescriptor cred_a_and_c(
4194+      device::CredentialType::kPublicKey,
4195+      std::vector<uint8_t>(kTestCredentialIdLength, 1),
4196+      // The union of the empty transports in `cred_a` plus the non-empty set
4197+      // from `cred_c` should still be empty, since empty set is interpreted to
4198+      // mean "any available transport".
4199+      {});
4200+  device::PublicKeyCredentialDescriptor cred_b_and_d(
4201+      device::CredentialType::kPublicKey,
4202+      std::vector<uint8_t>(kTestCredentialIdLength, 2),
4203+      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
4204+       device::FidoTransportProtocol::kBluetoothLowEnergy});
4205+  EXPECT_THAT(
4206+      virtual_device_factory_->mutable_state()->exclude_list_history.at(0),
4207+      testing::UnorderedElementsAre(cred_a_and_c, cred_b_and_d));
4208+}
4209+
4210+// Test that allow lists over 64 entries are verboten.
4211+TEST_F(AuthenticatorImplTest, OversizedAllowList) {
4212+  NavigateAndCommit(GURL(kTestOrigin1));
4213+
4214+  device::VirtualCtap2Device::Config config;
4215+  config.u2f_support = true;
4216+  config.max_credential_id_length = kTestCredentialIdLength;
4217+  config.max_credential_count_in_list = 100;
4218+  virtual_device_factory_->SetCtap2Config(config);
4219+
4220+  auto test_credentials = GetTestCredentials(
4221+      /*num_credentials=*/blink::mojom::
4222+          kPublicKeyCredentialDescriptorListMaxSize +
4223+      1);
4224+  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
4225+      test_credentials.at(0).id(), kTestRelyingPartyId));
4226+
4227+  PublicKeyCredentialRequestOptionsPtr options =
4228+      GetTestPublicKeyCredentialRequestOptions();
4229+  options->allow_credentials = test_credentials;
4230+
4231+  bool has_mojo_error = false;
4232+  SetMojoErrorHandler(base::BindLambdaForTesting(
4233+      [&](const std::string& error) { has_mojo_error = true; }));
4234+
4235+  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
4236+            AuthenticatorStatus::NOT_ALLOWED_ERROR);
4237+  EXPECT_TRUE(has_mojo_error);
4238+}
4239+
4240+// Test that exclude lists over 64 entries are verboten.
4241+TEST_F(AuthenticatorImplTest, OversizedExcludeList) {
4242+  NavigateAndCommit(GURL(kTestOrigin1));
4243+
4244+  device::VirtualCtap2Device::Config config;
4245+  config.u2f_support = true;
4246+  config.max_credential_id_length = kTestCredentialIdLength;
4247+  config.max_credential_count_in_list = 100;
4248+  virtual_device_factory_->SetCtap2Config(config);
4249+
4250+  auto test_credentials = GetTestCredentials(
4251+      /*num_credentials=*/blink::mojom::
4252+          kPublicKeyCredentialDescriptorListMaxSize +
4253+      1);
4254+
4255+  PublicKeyCredentialCreationOptionsPtr options =
4256+      GetTestPublicKeyCredentialCreationOptions();
4257+  options->exclude_credentials = test_credentials;
4258+
4259+  bool has_mojo_error = false;
4260+  SetMojoErrorHandler(base::BindLambdaForTesting(
4261+      [&](const std::string& error) { has_mojo_error = true; }));
4262+
4263+  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
4264+            AuthenticatorStatus::NOT_ALLOWED_ERROR);
4265+  EXPECT_TRUE(has_mojo_error);
4266+}
4267+
4268 TEST_F(AuthenticatorImplTest, NoUnexpectedAuthenticatorExtensions) {
4269   NavigateAndCommit(GURL(kTestOrigin1));
4270
4271diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
4272index 038bd22a6e..cb80baef7d 100644
4273--- a/content/browser/webauth/webauth_browsertest.cc
4274+++ b/content/browser/webauth/webauth_browsertest.cc
4275@@ -124,6 +124,14 @@ constexpr char kCrossOriginAncestorMessage[] =
4276     "storage/retrieval of 'PasswordCredential' and 'FederatedCredential', "
4277     "storage of 'PublicKeyCredential'.";
4278
4279+constexpr char kAllowCredentialsRangeErrorMessage[] =
4280+    "webauth: RangeError: The `allowCredentials` attribute exceeds the maximum "
4281+    "allowed size (64).";
4282+
4283+constexpr char kExcludeCredentialsRangeErrorMessage[] =
4284+    "webauth: RangeError: The `excludeCredentials` attribute exceeds the "
4285+    "maximum allowed size (64).";
4286+
4287 // Templates to be used with base::ReplaceStringPlaceholders. Can be
4288 // modified to include up to 9 replacements. The default values for
4289 // any additional replacements added should also be added to the
4290@@ -139,14 +147,14 @@ constexpr char kCreatePublicKeyTemplate[] =
4291     "    icon: '$8'},"
4292     "  pubKeyCredParams: [{ type: 'public-key', alg: '$4'}],"
4293     "  timeout: _timeout_,"
4294-    "  excludeCredentials: [],"
4295+    "  excludeCredentials: $9,"
4296     "  authenticatorSelection: {"
4297     "     requireResidentKey: $1,"
4298     "     userVerification: '$2',"
4299     "     authenticatorAttachment: '$5',"
4300     "  },"
4301     "  attestation: '$6',"
4302-    "}}).then(c => window.domAutomationController.send('webauth: OK' + $9),"
4303+    "}}).then(c => window.domAutomationController.send('webauth: OK'),"
4304     "         e => window.domAutomationController.send("
4305     "                  'webauth: ' + e.toString()));";
4306
4307@@ -161,40 +169,33 @@ constexpr char kCreatePublicKeyWithAbortSignalTemplate[] =
4308     "    icon: '$8'},"
4309     "  pubKeyCredParams: [{ type: 'public-key', alg: '$4'}],"
4310     "  timeout: _timeout_,"
4311-    "  excludeCredentials: [],"
4312+    "  excludeCredentials: $9,"
4313     "  authenticatorSelection: {"
4314     "     requireResidentKey: $1,"
4315     "     userVerification: '$2',"
4316     "     authenticatorAttachment: '$5',"
4317     "  },"
4318     "  attestation: '$6',"
4319-    "}, signal: $9}"
4320+    "}, signal: _signal_}"
4321     ").then(c => window.domAutomationController.send('webauth: OK'),"
4322     "       e => window.domAutomationController.send("
4323     "                'webauth: ' + e.toString()));";
4324
4325-constexpr char kPlatform[] = "platform";
4326-constexpr char kCrossPlatform[] = "cross-platform";
4327-constexpr char kPreferredVerification[] = "preferred";
4328-constexpr char kRequiredVerification[] = "required";
4329 constexpr char kShortTimeout[] = "100";
4330
4331 // Default values for kCreatePublicKeyTemplate.
4332 struct CreateParameters {
4333-  const char* rp_id = "acme.com";
4334+  std::string rp_id = "acme.com";
4335   bool require_resident_key = false;
4336-  const char* user_verification = kPreferredVerification;
4337-  const char* authenticator_attachment = kCrossPlatform;
4338-  const char* algorithm_identifier = "-7";
4339-  const char* attestation = "none";
4340-  const char* rp_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
4341-  const char* user_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
4342-  const char* signal = "";
4343-  // extra_ok_output is a Javascript expression which must evaluate to a string.
4344-  // It can use the |PublicKeyCredential| object named |c| to extract useful
4345-  // fields.
4346-  const char* extra_ok_output = "''";
4347-  const char* timeout = "1000";
4348+  std::string user_verification = "preferred";
4349+  std::string authenticator_attachment = "cross-platform";
4350+  std::string algorithm_identifier = "-7";
4351+  std::string attestation = "none";
4352+  std::string rp_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
4353+  std::string user_icon = "https://pics.acme.com/00/p/aBjjjpqPb.png";
4354+  std::string exclude_credentials = "[]";
4355+  std::string signal = "";
4356+  std::string timeout = "1000";
4357 };
4358
4359 std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
4360@@ -207,16 +208,17 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
4361   substitutions.push_back(parameters.attestation);
4362   substitutions.push_back(parameters.rp_icon);
4363   substitutions.push_back(parameters.user_icon);
4364+  substitutions.push_back(parameters.exclude_credentials);
4365
4366   std::string result;
4367-  if (strlen(parameters.signal) == 0) {
4368-    substitutions.push_back(parameters.extra_ok_output);
4369+  if (parameters.signal.empty()) {
4370     result = base::ReplaceStringPlaceholders(kCreatePublicKeyTemplate,
4371                                              substitutions, nullptr);
4372   } else {
4373-    substitutions.push_back(parameters.signal);
4374     result = base::ReplaceStringPlaceholders(
4375         kCreatePublicKeyWithAbortSignalTemplate, substitutions, nullptr);
4376+    base::ReplaceFirstSubstringAfterOffset(&result, 0, "_signal_",
4377+                                           parameters.signal);
4378   }
4379
4380   base::ReplaceFirstSubstringAfterOffset(&result, 0, "_timeout_",
4381@@ -227,45 +229,40 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
4382 constexpr char kGetPublicKeyTemplate[] =
4383     "navigator.credentials.get({ publicKey: {"
4384     "  challenge: new TextEncoder().encode('climb a mountain'),"
4385-    "  timeout: $4,"
4386     "  userVerification: '$1',"
4387-    "  $2}"
4388-    "}).then(c => window.domAutomationController.send('webauth: OK' + $3),"
4389+    "  allowCredentials: $2,"
4390+    "  timeout: $3}"
4391+    "}).then(c => window.domAutomationController.send('webauth: OK'),"
4392     "        e => window.domAutomationController.send("
4393     "                  'webauth: ' + e.toString()));";
4394
4395 constexpr char kGetPublicKeyWithAbortSignalTemplate[] =
4396     "navigator.credentials.get({ publicKey: {"
4397     "  challenge: new TextEncoder().encode('climb a mountain'),"
4398-    "  timeout: $4,"
4399     "  userVerification: '$1',"
4400-    "  $2},"
4401-    "  signal: $5"
4402-    "}).catch(c => window.domAutomationController.send("
4403+    "  allowCredentials: $2,"
4404+    "  timeout: $3,"
4405+    "}, signal: $4}"
4406+    ").catch(c => window.domAutomationController.send("
4407     "                  'webauth: ' + c.toString()));";
4408
4409 // Default values for kGetPublicKeyTemplate.
4410 struct GetParameters {
4411-  const char* user_verification = kPreferredVerification;
4412-  const char* allow_credentials =
4413-      "allowCredentials: [{ type: 'public-key',"
4414-      "     id: new TextEncoder().encode('allowedCredential'),"
4415-      "     transports: ['usb', 'nfc', 'ble']}]";
4416-  const char* signal = "";
4417-  const char* timeout = "1000";
4418-  // extra_ok_output is a Javascript expression which must evaluate to a string.
4419-  // It can use the |PublicKeyCredential| object named |c| to extract useful
4420-  // fields.
4421-  const char* extra_ok_output = "''";
4422+  std::string user_verification = "preferred";
4423+  std::string allow_credentials =
4424+      "[{type: 'public-key',"
4425+      "  id: new TextEncoder().encode('allowedCredential'),"
4426+      "  transports: ['usb', 'nfc', 'ble']}]";
4427+  std::string signal = "";
4428+  std::string timeout = "1000";
4429 };
4430
4431 std::string BuildGetCallWithParameters(const GetParameters& parameters) {
4432   std::vector<std::string> substitutions;
4433   substitutions.push_back(parameters.user_verification);
4434   substitutions.push_back(parameters.allow_credentials);
4435-  substitutions.push_back(parameters.extra_ok_output);
4436   substitutions.push_back(parameters.timeout);
4437-  if (strlen(parameters.signal) == 0) {
4438+  if (parameters.signal.empty()) {
4439     return base::ReplaceStringPlaceholders(kGetPublicKeyTemplate, substitutions,
4440                                            nullptr);
4441   }
4442@@ -886,7 +883,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4443     virtual_device_factory->SetSupportedProtocol(protocol);
4444
4445     CreateParameters parameters;
4446-    parameters.user_verification = kRequiredVerification;
4447+    parameters.user_verification = "required";
4448     parameters.timeout = kShortTimeout;
4449     std::string result;
4450     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
4451@@ -944,7 +941,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4452     virtual_device_factory->SetSupportedProtocol(protocol);
4453
4454     CreateParameters parameters;
4455-    parameters.authenticator_attachment = kPlatform;
4456+    parameters.authenticator_attachment = "platform";
4457     parameters.timeout = kShortTimeout;
4458     std::string result;
4459     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
4460@@ -1052,7 +1049,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4461
4462   GetParameters parameters;
4463   parameters.allow_credentials =
4464-      "allowCredentials: [{"
4465+      "[{"
4466       "  type: 'public-key',"
4467       "  id: new TextEncoder().encode('allowedCredential'),"
4468       "  transports: ['carrierpigeon'],"
4469@@ -1071,7 +1068,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4470                        GetPublicKeyCredentialEmptyAllowCredentialsList) {
4471   InjectVirtualFidoDeviceFactory();
4472   GetParameters parameters;
4473-  parameters.allow_credentials = "";
4474+  parameters.allow_credentials = "[]";
4475   std::string result;
4476   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
4477       shell()->web_contents()->GetMainFrame(),
4478@@ -1252,16 +1249,14 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4479       EXPECT_EQ(kCrossOriginAncestorMessage, result);
4480     }
4481
4482+    GetParameters get_params;
4483     const int credential_id =
4484         test.cross_origin ? kInnerCredentialID : kOuterCredentialID;
4485-    const std::string allow_credentials = base::StringPrintf(
4486-        "allowCredentials: "
4487+    get_params.allow_credentials = base::StringPrintf(
4488         "[{ type: 'public-key',"
4489         "   id: new Uint8Array([%d]),"
4490         "}]",
4491         credential_id);
4492-    GetParameters get_params;
4493-    get_params.allow_credentials = allow_credentials.c_str();
4494     ASSERT_TRUE(content::ExecuteScriptAndExtractString(
4495         iframe, BuildGetCallWithParameters(get_params), &result));
4496     if (test.get_should_work) {
4497@@ -1369,7 +1364,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4498   InjectVirtualFidoDeviceFactory();
4499   GetParameters parameters;
4500   parameters.allow_credentials =
4501-      "allowCredentials: [{ type: 'public-key',"
4502+      "[{ type: 'public-key',"
4503       "  id: new TextEncoder().encode('allowedCredential'),"
4504       "  transports: ['cable']}],"
4505       "extensions: {"
4506@@ -1466,8 +1461,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest, WinGetAssertion) {
4507
4508   GetParameters get_parameters;
4509   get_parameters.allow_credentials =
4510-      "allowCredentials: [{ type: 'public-key', id: new "
4511-      "TextEncoder().encode('AAA')}]";
4512+      "[{ type: 'public-key', id: new TextEncoder().encode('AAA')}]";
4513
4514   base::Optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
4515       shell()->web_contents(), BuildGetCallWithParameters(get_parameters),
4516@@ -1505,6 +1499,39 @@ IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4517 }
4518 #endif
4519
4520+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4521+                       GetAssertionOversizedAllowList) {
4522+  EXPECT_TRUE(
4523+      NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html")));
4524+
4525+  GetParameters get_parameters;
4526+  get_parameters.allow_credentials =
4527+      "Array(65).fill({ type: 'public-key', id: new "
4528+      "TextEncoder().encode('A')})";
4529+
4530+  absl::optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
4531+      shell()->web_contents(), BuildGetCallWithParameters(get_parameters),
4532+      "webauth: ");
4533+  ASSERT_TRUE(result);
4534+  ASSERT_EQ(kAllowCredentialsRangeErrorMessage, *result);
4535+}
4536+
4537+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
4538+                       MakeCredentialOversizedExcludeList) {
4539+  EXPECT_TRUE(
4540+      NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html")));
4541+
4542+  CreateParameters parameters;
4543+  parameters.exclude_credentials =
4544+      "Array(65).fill({type: 'public-key', id: new TextEncoder().encode('A')})";
4545+
4546+  absl::optional<std::string> result = ExecuteScriptAndExtractPrefixedString(
4547+      shell()->web_contents(), BuildCreateCallWithParameters(parameters),
4548+      "webauth: ");
4549+  ASSERT_TRUE(result);
4550+  ASSERT_EQ(kExcludeCredentialsRangeErrorMessage, *result);
4551+}
4552+
4553 class WebAuthLocalClientBackForwardCacheBrowserTest
4554     : public WebAuthLocalClientBrowserTest {
4555  protected:
4556diff --git a/content/browser/webauth/webauth_request_security_checker.cc b/content/browser/webauth/webauth_request_security_checker.cc
4557index 57201e51bc..e4db00509e 100644
4558--- a/content/browser/webauth/webauth_request_security_checker.cc
4559+++ b/content/browser/webauth/webauth_request_security_checker.cc
4560@@ -10,6 +10,7 @@
4561 #include "content/public/browser/render_frame_host.h"
4562 #include "content/public/common/content_features.h"
4563 #include "device/fido/features.h"
4564+#include "device/fido/fido_transport_protocol.h"
4565 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
4566 #include "services/network/public/cpp/is_potentially_trustworthy.h"
4567 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
4568@@ -185,4 +186,51 @@ WebAuthRequestSecurityChecker::ValidateAPrioriAuthenticatedUrl(
4569   return blink::mojom::AuthenticatorStatus::SUCCESS;
4570 }
4571
4572+bool WebAuthRequestSecurityChecker::
4573+    DeduplicateCredentialDescriptorListAndValidateLength(
4574+        std::vector<device::PublicKeyCredentialDescriptor>* list) {
4575+  // Credential descriptor lists should not exceed 64 entries, which is enforced
4576+  // by renderer code. Any duplicate entries they contain should be ignored.
4577+  // This is to guard against sites trying to amplify small timing differences
4578+  // in the processing of different types of credentials when sending probing
4579+  // requests to physical security keys (https://crbug.com/1248862).
4580+  if (list->size() > blink::mojom::kPublicKeyCredentialDescriptorListMaxSize) {
4581+    return false;
4582+  }
4583+  auto credential_descriptor_compare_without_transport =
4584+      [](const device::PublicKeyCredentialDescriptor& a,
4585+         const device::PublicKeyCredentialDescriptor& b) {
4586+        return a.credential_type() < b.credential_type() ||
4587+               (a.credential_type() == b.credential_type() && a.id() < b.id());
4588+      };
4589+  std::set<device::PublicKeyCredentialDescriptor,
4590+           decltype(credential_descriptor_compare_without_transport)>
4591+      unique_credential_descriptors(
4592+          credential_descriptor_compare_without_transport);
4593+  for (const auto& credential_descriptor : *list) {
4594+    auto it = unique_credential_descriptors.find(credential_descriptor);
4595+    if (it == unique_credential_descriptors.end()) {
4596+      unique_credential_descriptors.insert(credential_descriptor);
4597+    } else {
4598+      // Combine transport hints of descriptors with identical IDs. Empty
4599+      // transport list means _any_ transport, so the union should still be
4600+      // empty.
4601+      base::flat_set<device::FidoTransportProtocol> merged_transports;
4602+      if (!it->transports().empty() &&
4603+          !credential_descriptor.transports().empty()) {
4604+        base::ranges::set_union(
4605+            it->transports(), credential_descriptor.transports(),
4606+            std::inserter(merged_transports, merged_transports.begin()));
4607+      }
4608+      unique_credential_descriptors.erase(it);
4609+      unique_credential_descriptors.insert(
4610+          {credential_descriptor.credential_type(), credential_descriptor.id(),
4611+           std::move(merged_transports)});
4612+    }
4613+  }
4614+  *list = {unique_credential_descriptors.begin(),
4615+           unique_credential_descriptors.end()};
4616+  return true;
4617+}
4618+
4619 }  // namespace content
4620diff --git a/content/browser/webauth/webauth_request_security_checker.h b/content/browser/webauth/webauth_request_security_checker.h
4621index d1cb8f730e..9e26ed2524 100644
4622--- a/content/browser/webauth/webauth_request_security_checker.h
4623+++ b/content/browser/webauth/webauth_request_security_checker.h
4624@@ -10,6 +10,7 @@
4625 #include "base/memory/ref_counted.h"
4626 #include "base/optional.h"
4627 #include "content/common/content_export.h"
4628+#include "device/fido/public_key_credential_descriptor.h"
4629 #include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
4630
4631 namespace url {
4632@@ -71,6 +72,10 @@ class CONTENT_EXPORT WebAuthRequestSecurityChecker
4633   blink::mojom::AuthenticatorStatus ValidateAPrioriAuthenticatedUrl(
4634       const GURL& url);
4635
4636+  bool DeduplicateCredentialDescriptorListAndValidateLength(
4637+      std::vector<device::PublicKeyCredentialDescriptor>* list)
4638+      WARN_UNUSED_RESULT;
4639+
4640  protected:
4641   friend class RefCounted<WebAuthRequestSecurityChecker>;
4642   virtual ~WebAuthRequestSecurityChecker();
4643diff --git a/content/public/browser/background_fetch_delegate.h b/content/public/browser/background_fetch_delegate.h
4644index 09436ef773..02e1255480 100644
4645--- a/content/public/browser/background_fetch_delegate.h
4646+++ b/content/public/browser/background_fetch_delegate.h
4647@@ -16,6 +16,7 @@
4648 #include "base/optional.h"
4649 #include "content/common/content_export.h"
4650 #include "content/public/browser/web_contents.h"
4651+#include "services/network/public/mojom/fetch_api.mojom-shared.h"
4652 #include "third_party/blink/public/mojom/background_fetch/background_fetch.mojom.h"
4653 #include "third_party/skia/include/core/SkBitmap.h"
4654
4655@@ -140,6 +141,7 @@ class CONTENT_EXPORT BackgroundFetchDelegate {
4656       const std::string& download_guid,
4657       const std::string& method,
4658       const GURL& url,
4659+      ::network::mojom::CredentialsMode credentials_mode,
4660       const net::NetworkTrafficAnnotationTag& traffic_annotation,
4661       const net::HttpRequestHeaders& headers,
4662       bool has_request_body) = 0;
4663diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
4664index f2f81b235f..b4ae72f795 100644
4665--- a/content/public/browser/content_browser_client.h
4666+++ b/content/public/browser/content_browser_client.h
4667@@ -1718,10 +1718,12 @@ class CONTENT_EXPORT ContentBrowserClient {
4668   // Otherwise child_id will be the process id and |navigation_ui_data| will be
4669   // nullptr.
4670   //
4671-  // |initiating_origin| is the origin that initiated the navigation to the
4672-  // external protocol, and may be null, e.g. in the case of browser-initiated
4673-  // navigations. The initiating origin is intended to help users make security
4674-  // decisions about whether to allow an external application to launch.
4675+  // |initiating_origin| is the origin of the last redirecting server (falling
4676+  // back to the request initiator if there were no redirects / if the request
4677+  // goes straight to an external protocol, or null, e.g. in the case of
4678+  // browser-initiated navigations. The initiating origin is intended to help
4679+  // users make security decisions about whether to allow an external
4680+  // application to launch.
4681   virtual bool HandleExternalProtocol(
4682       const GURL& url,
4683       base::OnceCallback<WebContents*()> web_contents_getter,
4684diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
4685index 3e6645553b..b07486bc45 100644
4686--- a/content/public/common/content_features.cc
4687+++ b/content/public/common/content_features.cc
4688@@ -649,7 +649,7 @@ const base::Feature kServiceWorkerTerminationOnNoControllee{
4689 // isolated renderers.
4690 const base::Feature kSharedArrayBuffer {
4691   "SharedArrayBuffer",
4692-#if defined(OS_ANDROID)
4693+#if defined(OS_ANDROID) || defined(OS_OHOS)
4694       base::FEATURE_DISABLED_BY_DEFAULT
4695 #else
4696       base::FEATURE_ENABLED_BY_DEFAULT
4697@@ -814,7 +814,7 @@ const base::Feature kWebAssemblyTiering{"WebAssemblyTiering",
4698 // isolated renderers.
4699 const base::Feature kWebAssemblyThreads {
4700   "WebAssemblyThreads",
4701-#if defined(OS_ANDROID)
4702+#if defined(OS_ANDROID) || defined(OS_OHOS)
4703       base::FEATURE_DISABLED_BY_DEFAULT
4704 #else
4705       base::FEATURE_ENABLED_BY_DEFAULT
4706diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
4707index f543db60a3..61ccb23398 100644
4708--- a/content/public/common/content_switches.cc
4709+++ b/content/public/common/content_switches.cc
4710@@ -973,6 +973,7 @@ const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
4711
4712 #if defined(OS_OHOS)
4713 const char kEnableMultiRendererProcess[] = "enable-multi-renderer-process";
4714+const char kForTest[] = "for-test";
4715 #endif
4716
4717 #if defined(OS_WIN)
4718diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
4719index 31d0a72c4b..deb45f55a2 100644
4720--- a/content/public/common/content_switches.h
4721+++ b/content/public/common/content_switches.h
4722@@ -267,6 +267,7 @@ CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
4723 // of lacros-chrome is complete.
4724 #if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || defined(OS_OHOS)
4725 CONTENT_EXPORT extern const char kEnableSpeechDispatcher[];
4726+CONTENT_EXPORT extern const char kForTest[];
4727 #endif
4728
4729 #if defined(OS_OHOS)
4730diff --git a/content/public/test/fake_download_item.cc b/content/public/test/fake_download_item.cc
4731index 5cd2ba5ff4..5bc7cc74f4 100644
4732--- a/content/public/test/fake_download_item.cc
4733+++ b/content/public/test/fake_download_item.cc
4734@@ -207,6 +207,15 @@ FakeDownloadItem::GetDownloadSchedule() const {
4735   return download_schedule_;
4736 }
4737
4738+::network::mojom::CredentialsMode FakeDownloadItem::GetCredentialsMode() const {
4739+  return ::network::mojom::CredentialsMode::kInclude;
4740+}
4741+
4742+const absl::optional<net::IsolationInfo>& FakeDownloadItem::GetIsolationInfo()
4743+    const {
4744+  return isolation_info_;
4745+}
4746+
4747 void FakeDownloadItem::SetIsDone(bool is_done) {
4748   is_done_ = is_done;
4749 }
4750diff --git a/content/public/test/fake_download_item.h b/content/public/test/fake_download_item.h
4751index 7d6bb806ca..caa7ebc255 100644
4752--- a/content/public/test/fake_download_item.h
4753+++ b/content/public/test/fake_download_item.h
4754@@ -59,6 +59,8 @@ class FakeDownloadItem : public download::DownloadItem {
4755   DownloadCreationType GetDownloadCreationType() const override;
4756   const base::Optional<download::DownloadSchedule>& GetDownloadSchedule()
4757       const override;
4758+  ::network::mojom::CredentialsMode GetCredentialsMode() const override;
4759+  const absl::optional<net::IsolationInfo>& GetIsolationInfo() const override;
4760   bool IsDone() const override;
4761   const std::string& GetETag() const override;
4762   const std::string& GetLastModifiedTime() const override;
4763@@ -186,6 +188,7 @@ class FakeDownloadItem : public download::DownloadItem {
4764   std::string last_modified_time_;
4765   std::string hash_;
4766   base::Optional<download::DownloadSchedule> download_schedule_;
4767+  absl::optional<net::IsolationInfo> isolation_info_;
4768
4769   // The members below are to be returned by methods, which return by reference.
4770   std::string dummy_string;
4771diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn
4772index dd529be39b..9325b96383 100644
4773--- a/content/renderer/BUILD.gn
4774+++ b/content/renderer/BUILD.gn
4775@@ -19,6 +19,26 @@ if (is_component_build) {
4776   link_target_type = "static_library"
4777 }
4778
4779+if (is_ohos) {
4780+  import("//build/config/ohos/config.gni")
4781+  config("ohos_system_libs") {
4782+    libs = [
4783+      "hilog",
4784+      "utils.z",
4785+      "eventhandler.z",
4786+      "app_manager.z",
4787+      "base.z",
4788+      "want.z",
4789+      "appexecfwk_common.z",
4790+      "appexecfwk_base.z",
4791+      "samgr_proxy.z",
4792+      "ipc_core.z",
4793+    ]
4794+    include_dirs = ohos_src_includes
4795+    lib_dirs = ohos_libs_dir
4796+  }
4797+}
4798+
4799 target(link_target_type, "renderer") {
4800   # Only the public target should depend on this. All other targets (even
4801   # internal content ones) should depend on the public one.
4802@@ -216,11 +236,14 @@ target(link_target_type, "renderer") {
4803   }
4804
4805   if (is_ohos) {
4806+    configs += [ ":ohos_system_libs" ]
4807     sources += [
4808       "media/ohos/ohos_media_player_renderer_client.cc",
4809       "media/ohos/ohos_media_player_renderer_client.h",
4810       "media/ohos/ohos_media_player_renderer_client_factory.cc",
4811       "media/ohos/ohos_media_player_renderer_client_factory.h",
4812+      "render_remote_proxy.h",
4813+      "render_remote_proxy.cc",
4814     ]
4815   }
4816
4817diff --git a/content/renderer/media/ohos/ohos_media_player_renderer_client.cc b/content/renderer/media/ohos/ohos_media_player_renderer_client.cc
4818index 4f2b9c1043..666e08857c 100644
4819--- a/content/renderer/media/ohos/ohos_media_player_renderer_client.cc
4820+++ b/content/renderer/media/ohos/ohos_media_player_renderer_client.cc
4821@@ -8,6 +8,8 @@
4822 #include <sys/stat.h>
4823 #include <utility>
4824
4825+#include <display_type.h>
4826+#include <cerrno>
4827 #include "base/logging.h"
4828 #include "media/base/video_frame.h"
4829
4830@@ -30,7 +32,7 @@ OHOSMediaPlayerRendererClient::OHOSMediaPlayerRendererClient(
4831
4832 OHOSMediaPlayerRendererClient::~OHOSMediaPlayerRendererClient() {
4833   while (!cached_buffers_.empty()) {
4834-    CachedBuffer &temp_buffer = cached_buffers_.front();
4835+    CachedBuffer& temp_buffer = cached_buffers_.front();
4836     munmap(temp_buffer.mapped_, temp_buffer.buffer_size_);
4837     close(temp_buffer.fd_);
4838     cached_buffers_.pop_front();
4839@@ -73,7 +75,7 @@ void OHOSMediaPlayerRendererClient::OnFinishPaintCallback() {
4840     return;
4841   }
4842   if (cached_buffers_.size() > 1) {
4843-    CachedBuffer &temp_buffer = cached_buffers_.front();
4844+    CachedBuffer& temp_buffer = cached_buffers_.front();
4845     munmap(temp_buffer.mapped_, temp_buffer.buffer_size_);
4846     close(temp_buffer.fd_);
4847     renderer_extension_remote_->FinishPaint(temp_buffer.fd_browser_);
4848@@ -120,21 +122,69 @@ void OHOSMediaPlayerRendererClient::OnFrameUpdate(
4849   auto fd = ohos_surface_buffer_handle->buffer_fd.TakeFD().release();
4850   uint32_t buffer_size = ohos_surface_buffer_handle->buffer_size;
4851   int fd_browser = ohos_surface_buffer_handle->fd_browser;
4852-  int32_t width = ohos_surface_buffer_handle->width;
4853-  int32_t height = ohos_surface_buffer_handle->height;
4854-
4855+  int32_t coded_width = ohos_surface_buffer_handle->coded_width;
4856+  int32_t coded_height = ohos_surface_buffer_handle->coded_height;
4857+  int32_t visible_width = ohos_surface_buffer_handle->visible_width;
4858+  int32_t visible_height = ohos_surface_buffer_handle->visible_height;
4859+  int32_t src_format = ohos_surface_buffer_handle->format;
4860+  errno = 0;
4861   uint8_t* mapped =
4862       (uint8_t*)mmap(NULL, buffer_size, PROT_READ, MAP_SHARED, fd, 0);
4863+  int temp_errno = errno;
4864+  if (temp_errno != 0) {
4865+    LOG(ERROR) << "Render client map failed err:" << temp_errno
4866+               << " coded_width:" << coded_width
4867+               << " coded_height:" << coded_height
4868+               << " visible_width:" << visible_width
4869+               << " visible_height:" << visible_height
4870+               << " mmap:" << (void*)mapped
4871+               << " fd:" << fd
4872+               << " format:" << src_format << " size:" << buffer_size;
4873+  }
4874+  gfx::Size coded_size = gfx::Size(coded_width, coded_height);
4875+  gfx::Rect visible_rect = gfx::Rect(0, 0, visible_width, visible_height);
4876+  gfx::Size natural_size = gfx::Size(visible_width, visible_height);
4877   const base::TimeDelta kZero;
4878+  if (src_format == PIXEL_FMT_YCBCR_420_SP) {
4879+    PaintNV12VideoFrame(coded_size, visible_rect, natural_size, mapped,
4880+                        buffer_size, fd, fd_browser);
4881+  } else {
4882+    scoped_refptr<media::VideoFrame> dst_frame =
4883+        media::VideoFrame::WrapExternalData(
4884+            media::VideoPixelFormat::PIXEL_FORMAT_ABGR, coded_size,
4885+            visible_rect, natural_size, mapped, buffer_size, kZero);
4886+    sink_->PaintSingleFrame(std::move(dst_frame));
4887+    cached_buffers_.push_back(
4888+        CachedBuffer{fd_browser, fd, mapped, buffer_size});
4889+  }
4890+}
4891
4892-  media::VideoPixelFormat format = media::VideoPixelFormat::PIXEL_FORMAT_ABGR;
4893-  gfx::Size size = gfx::Size(width, height);
4894-  scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapExternalData(
4895-      format, size, gfx::Rect(size), size, mapped, buffer_size, kZero);
4896-
4897-  auto unique_frame = media::VideoFrame::WrapVideoFrame(
4898-      frame, frame->format(), frame->visible_rect(), frame->natural_size());
4899-  sink_->PaintSingleFrame(std::move(unique_frame));
4900+void OHOSMediaPlayerRendererClient::PaintNV12VideoFrame(
4901+    const gfx::Size& coded_size,
4902+    const gfx::Rect& visible_rect,
4903+    const gfx::Size& natural_size,
4904+    uint8_t* mapped,
4905+    const uint32_t& buffer_size,
4906+    const int& fd,
4907+    const int& fd_browser) {
4908+  const base::TimeDelta kZero;
4909+  scoped_refptr<media::VideoFrame> src_frame =
4910+      media::VideoFrame::WrapExternalData(
4911+          media::VideoPixelFormat::PIXEL_FORMAT_NV12, coded_size, visible_rect,
4912+          natural_size, mapped, buffer_size, kZero);
4913+  scoped_refptr<media::VideoFrame> dst_frame = media::VideoFrame::CreateFrame(
4914+      media::VideoPixelFormat::PIXEL_FORMAT_I420, coded_size, visible_rect,
4915+      natural_size, src_frame->timestamp());
4916+  auto convert_status =
4917+      media::ConvertAndScaleFrame(*src_frame, *dst_frame, resize_buf_);
4918+  if (!convert_status.is_ok()) {
4919+    LOG(ERROR) << "Convert failed msg:" << convert_status.message();
4920+    munmap(mapped, buffer_size);
4921+    close(fd);
4922+    renderer_extension_remote_->FinishPaint(fd_browser);
4923+    return;
4924+  }
4925+  sink_->PaintSingleFrame(std::move(dst_frame));
4926   cached_buffers_.push_back(CachedBuffer{fd_browser, fd, mapped, buffer_size});
4927 }
4928
4929diff --git a/content/renderer/media/ohos/ohos_media_player_renderer_client.h b/content/renderer/media/ohos/ohos_media_player_renderer_client.h
4930index 8f1f6cf0da..040f39fc9f 100644
4931--- a/content/renderer/media/ohos/ohos_media_player_renderer_client.h
4932+++ b/content/renderer/media/ohos/ohos_media_player_renderer_client.h
4933@@ -16,6 +16,7 @@
4934 #include "media/base/renderer.h"
4935 #include "media/base/renderer_client.h"
4936 #include "media/base/video_renderer_sink.h"
4937+#include "media/base/video_util.h"
4938 #include "media/mojo/clients/mojo_renderer.h"
4939 #include "media/mojo/clients/mojo_renderer_wrapper.h"
4940 #include "media/mojo/mojom/renderer_extensions.mojom.h"
4941@@ -62,6 +63,14 @@ class OHOSMediaPlayerRendererClient
4942   void OnRemoteRendererInitialized(media::PipelineStatus status);
4943   void OnFinishPaintCallback();
4944
4945+  void PaintNV12VideoFrame(const gfx::Size& coded_size,
4946+                           const gfx::Rect& visible_rect,
4947+                           const gfx::Size& natural_size,
4948+                           uint8_t* mapped,
4949+                           const uint32_t& buffer_size,
4950+                           const int& fd,
4951+                           const int& fd_browser);
4952+
4953   media::MediaResource* media_resource_;
4954
4955   std::deque<CachedBuffer> cached_buffers_;
4956@@ -74,6 +83,8 @@ class OHOSMediaPlayerRendererClient
4957
4958   media::PipelineStatusCallback init_cb_;
4959
4960+  std::vector<uint8_t> resize_buf_;
4961+
4962   // This class is constructed on the main task runner, and used on
4963   // |media_task_runner_|. These member are used to delay calls to Bind() for
4964   // |renderer_extension_ptr_| and |client_extension_binding_|, until we are on
4965diff --git a/content/renderer/render_remote_proxy.cc b/content/renderer/render_remote_proxy.cc
4966new file mode 100644
4967index 0000000000..2fada4e83b
4968--- /dev/null
4969+++ b/content/renderer/render_remote_proxy.cc
4970@@ -0,0 +1,78 @@
4971+// Copyright 2022 The Huawei Authors. All rights reserved.
4972+// Use of this source code is governed by a BSD-style license that can be
4973+// found in the LICENSE file.
4974+
4975+#include "render_remote_proxy.h"
4976+
4977+#include <thread>
4978+#include "appmgr/app_mgr_client.h"
4979+#include "base/command_line.h"
4980+#include "base/posix/global_descriptors.h"
4981+#include "content/public/common/content_descriptors.h"
4982+#include "content/public/common/content_switches.h"
4983+#include "refbase.h"
4984+
4985+namespace content {
4986+std::unique_ptr<OHOS::AppExecFwk::AppMgrClient> g_app_mgr_client{nullptr};
4987+OHOS::sptr<RenderRemoteProxy> g_render_remote_proxy{nullptr};
4988+
4989+std::mutex RenderRemoteProxy::browser_fd_mtx_;
4990+std::condition_variable RenderRemoteProxy::browser_fd_cv_;
4991+bool RenderRemoteProxy::is_browser_fd_received_{false};
4992+bool RenderRemoteProxy::is_for_test_{false};
4993+
4994+void RenderRemoteProxy::NotifyBrowserFd(int32_t ipcFd, int32_t sharedFd) {
4995+  base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
4996+  if (g_fds != nullptr) {
4997+    int new_ipc_fd;
4998+    if ((new_ipc_fd = dup(ipcFd)) < 0) {
4999+      LOG(ERROR) << "ipcFd duplicate error";
5000+      g_fds->Set(kMojoIPCChannel, ipcFd);
5001+      ipc_fd_ = ipcFd;
5002+    } else {
5003+      g_fds->Set(kMojoIPCChannel, new_ipc_fd);
5004+      ipc_fd_ = new_ipc_fd;
5005+      close(ipcFd);
5006+    }
5007+
5008+    int new_shared_fd;
5009+    if ((new_shared_fd = dup(sharedFd)) < 0) {
5010+      LOG(ERROR) << "sharedFd duplicate error";
5011+      g_fds->Set(kFieldTrialDescriptor, sharedFd);
5012+      shared_fd_ = sharedFd;
5013+    } else {
5014+      g_fds->Set(kFieldTrialDescriptor, new_shared_fd);
5015+      shared_fd_ = new_shared_fd;
5016+      close(sharedFd);
5017+    }
5018+  }
5019+  RenderRemoteProxy::is_browser_fd_received_ = true;
5020+  RenderRemoteProxy::browser_fd_cv_.notify_one();
5021+}
5022+
5023+void RenderRemoteProxy::CreateAndRegist(const base::CommandLine& command_line) {
5024+  is_for_test_ = command_line.HasSwitch(switches::kForTest);
5025+  if (!is_for_test_) {
5026+    g_app_mgr_client = std::make_unique<OHOS::AppExecFwk::AppMgrClient>();
5027+    g_render_remote_proxy = new RenderRemoteProxy();
5028+    g_app_mgr_client->AttachRenderProcess(g_render_remote_proxy);
5029+  }
5030+}
5031+
5032+bool RenderRemoteProxy::WaitForBrowserFd() {
5033+  if (is_for_test_) {
5034+    return true;
5035+  }
5036+  LOG(INFO) << "wait for browser fd start";
5037+  std::unique_lock<std::mutex> lk(browser_fd_mtx_);
5038+  constexpr int kTimeOutDur = 5;  // seconds
5039+  if (!browser_fd_cv_.wait_for(lk, std::chrono::seconds(kTimeOutDur),
5040+                               []() { return is_browser_fd_received_; })) {
5041+    LOG(ERROR) << "wait for browser fd timeout(" << kTimeOutDur << "s)";
5042+    return false;
5043+  }
5044+  LOG(INFO) << "wait for browser fd end";
5045+  return true;
5046+}
5047+
5048+} // namespace content
5049\ No newline at end of file
5050diff --git a/content/renderer/render_remote_proxy.h b/content/renderer/render_remote_proxy.h
5051new file mode 100644
5052index 0000000000..1127280fbf
5053--- /dev/null
5054+++ b/content/renderer/render_remote_proxy.h
5055@@ -0,0 +1,39 @@
5056+// Copyright 2022 The Huawei Authors. All rights reserved.
5057+// Use of this source code is governed by a BSD-style license that can be
5058+// found in the LICENSE file.
5059+
5060+#ifndef CONTENT_RENDERER_RENDER_REMOTE_PROXY_H_
5061+#define CONTENT_RENDERER_RENDER_REMOTE_PROXY_H_
5062+
5063+#include <condition_variable>
5064+#include <mutex>
5065+#include "appmgr/render_scheduler_host.h"
5066+
5067+namespace base {
5068+class CommandLine;
5069+}
5070+
5071+namespace content {
5072+class RenderRemoteProxy : public OHOS::AppExecFwk::RenderSchedulerHost {
5073+ public:
5074+  RenderRemoteProxy() = default;
5075+  ~RenderRemoteProxy() = default;
5076+
5077+  virtual void NotifyBrowserFd(int32_t ipcFd, int32_t sharedFd) override;
5078+
5079+  static void CreateAndRegist(const base::CommandLine& command_line);
5080+  static bool WaitForBrowserFd();
5081+
5082+ private:
5083+  int32_t ipc_fd_ = 0;
5084+  int32_t shared_fd_ = 0;
5085+
5086+  static std::mutex browser_fd_mtx_;
5087+  static std::condition_variable browser_fd_cv_;
5088+  static bool is_browser_fd_received_;
5089+  static bool is_for_test_;
5090+};
5091+
5092+}  // namespace content
5093+
5094+#endif  // CONTENT_RENDERER_RENDER_REMOTE_PROXY_H_
5095\ No newline at end of file
5096diff --git a/content/renderer/service_worker/navigation_preload_request.cc b/content/renderer/service_worker/navigation_preload_request.cc
5097index 231e947e15..0e8d77666e 100644
5098--- a/content/renderer/service_worker/navigation_preload_request.cc
5099+++ b/content/renderer/service_worker/navigation_preload_request.cc
5100@@ -17,12 +17,12 @@ NavigationPreloadRequest::NavigationPreloadRequest(
5101     ServiceWorkerContextClient* owner,
5102     int fetch_event_id,
5103     const GURL& url,
5104-    blink::mojom::FetchEventPreloadHandlePtr preload_handle)
5105+    mojo::PendingReceiver<network::mojom::URLLoaderClient>
5106+        preload_url_loader_client_receiver)
5107     : owner_(owner),
5108       fetch_event_id_(fetch_event_id),
5109       url_(url),
5110-      url_loader_(std::move(preload_handle->url_loader)),
5111-      receiver_(this, std::move(preload_handle->url_loader_client_receiver)) {}
5112+      receiver_(this, std::move(preload_url_loader_client_receiver)) {}
5113
5114 NavigationPreloadRequest::~NavigationPreloadRequest() = default;
5115
5116diff --git a/content/renderer/service_worker/navigation_preload_request.h b/content/renderer/service_worker/navigation_preload_request.h
5117index 639cc6f086..fc9c5c66b4 100644
5118--- a/content/renderer/service_worker/navigation_preload_request.h
5119+++ b/content/renderer/service_worker/navigation_preload_request.h
5120@@ -34,7 +34,8 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
5121       ServiceWorkerContextClient* owner,
5122       int fetch_event_id,
5123       const GURL& url,
5124-      blink::mojom::FetchEventPreloadHandlePtr preload_handle);
5125+      mojo::PendingReceiver<network::mojom::URLLoaderClient>
5126+          preload_url_loader_client_receiver);
5127   ~NavigationPreloadRequest() override;
5128
5129   // network::mojom::URLLoaderClient:
5130@@ -58,11 +59,10 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
5131   void ReportErrorToOwner(const std::string& message,
5132                           blink::WebServiceWorkerError::Mode error_mode);
5133
5134-  ServiceWorkerContextClient* owner_;
5135+  ServiceWorkerContextClient* owner_ = nullptr;
5136
5137-  const int fetch_event_id_;
5138+  const int fetch_event_id_ = -1;
5139   const GURL url_;
5140-  mojo::Remote<network::mojom::URLLoader> url_loader_;
5141   mojo::Receiver<network::mojom::URLLoaderClient> receiver_;
5142
5143   std::unique_ptr<blink::WebURLResponse> response_;
5144diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
5145index 79334c2ebf..9a1e9a6594 100644
5146--- a/content/renderer/service_worker/service_worker_context_client.cc
5147+++ b/content/renderer/service_worker/service_worker_context_client.cc
5148@@ -475,14 +475,14 @@ void ServiceWorkerContextClient::SendWorkerStarted(
5149 void ServiceWorkerContextClient::SetupNavigationPreload(
5150     int fetch_event_id,
5151     const blink::WebURL& url,
5152-    std::unique_ptr<blink::WebFetchEventPreloadHandle> preload_handle) {
5153+    blink::CrossVariantMojoReceiver<
5154+        network::mojom::URLLoaderClientInterfaceBase>
5155+        preload_url_loader_client_receiver) {
5156   DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
5157   DCHECK(context_);
5158   auto preload_request = std::make_unique<NavigationPreloadRequest>(
5159       this, fetch_event_id, GURL(url),
5160-      blink::mojom::FetchEventPreloadHandle::New(
5161-          std::move(preload_handle->url_loader),
5162-          std::move(preload_handle->url_loader_client_receiver)));
5163+      std::move(preload_url_loader_client_receiver));
5164   context_->preload_requests.AddWithID(std::move(preload_request),
5165                                        fetch_event_id);
5166 }
5167diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
5168index 8191aaec6e..5abd533c6c 100644
5169--- a/content/renderer/service_worker/service_worker_context_client.h
5170+++ b/content/renderer/service_worker/service_worker_context_client.h
5171@@ -159,8 +159,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient
5172                             const blink::WebString& source_url) override;
5173   void SetupNavigationPreload(int fetch_event_id,
5174                               const blink::WebURL& url,
5175-                              std::unique_ptr<blink::WebFetchEventPreloadHandle>
5176-                                  preload_handle) override;
5177+                              blink::CrossVariantMojoReceiver<
5178+                                  network::mojom::URLLoaderClientInterfaceBase>
5179+                                  preload_url_loader_client_receiver) override;
5180   void RequestTermination(RequestTerminationCallback callback) override;
5181   scoped_refptr<blink::WebServiceWorkerFetchContext>
5182   CreateWorkerFetchContextOnInitiatorThread() override;
5183diff --git a/content/test/data/gpu/webgpu-stress-request-device-and-remove-loop.html b/content/test/data/gpu/webgpu-stress-request-device-and-remove-loop.html
5184new file mode 100644
5185index 0000000000..715688a634
5186--- /dev/null
5187+++ b/content/test/data/gpu/webgpu-stress-request-device-and-remove-loop.html
5188@@ -0,0 +1,58 @@
5189+<!--
5190+  This is a stress test for crbug.com/1242269.
5191+  In the bug, a flaky use-after-free could happen depending on the ordering of
5192+  the Javascript ExecutionContext ContextDestroyed notification and GC finalization
5193+  of the GPUDevice in the page. Repeatingly creating an iframe, initializing a GPUDevice,
5194+  and then destroying the iframe can sometimes hit this and crash. This test does this
5195+  repeatedly with many iframes at once for 90 seconds.
5196+-->
5197+<head>
5198+  <script>
5199+    const iframes = [];
5200+    function removeOneIframe() {
5201+      setTimeout(function () {
5202+        document.body.removeChild(iframes.shift());
5203+      }, Math.random() * 500);
5204+    }
5205+
5206+    async function run() {
5207+      if (window.domAutomationController) {
5208+        window.domAutomationController.send('LOADED');
5209+        setTimeout(() => {
5210+          // Succeed if don't crash within 90 seconds.
5211+          window.domAutomationController.send('SUCCESS');
5212+        }, 90 * 1000);
5213+      }
5214+
5215+      while (true) {
5216+        const iframe = document.createElement("iframe");
5217+        iframe.setAttribute("id", "iframe");
5218+        document.body.appendChild(iframe);
5219+
5220+        iframes.push(iframe);
5221+
5222+        const head = iframe.contentWindow.document.getElementsByTagName('head')[0];
5223+        const script = iframe.contentWindow.document.createElement('script');
5224+        script.type = 'text/javascript';
5225+        script.innerText = `
5226+          navigator.gpu.requestAdapter().then((adapter) => {
5227+            adapter.requestDevice().then((val) => {
5228+              parent.removeOneIframe();
5229+            });
5230+          });
5231+        `;
5232+        head.appendChild(script);
5233+
5234+        // Wait a bit to yield to the event loop.
5235+        await new Promise(resolve => setTimeout(resolve, 0));
5236+
5237+        // Avoid having too many iframes in flight.
5238+        while (iframes.length > 100) {
5239+          await new Promise(resolve => setTimeout(resolve, 100));
5240+        }
5241+      }
5242+    }
5243+  </script>
5244+</head>
5245+
5246+<body onload="run()"></body>
5247diff --git a/content/test/gpu/gpu_tests/context_lost_integration_test.py b/content/test/gpu/gpu_tests/context_lost_integration_test.py
5248index 6a3d4717c7..9096205323 100644
5249--- a/content/test/gpu/gpu_tests/context_lost_integration_test.py
5250+++ b/content/test/gpu/gpu_tests/context_lost_integration_test.py
5251@@ -148,6 +148,8 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest):
5252               'gpu_process_crash.html'),
5253              ('ContextLost_WebGPUContextLostFromGPUProcessExit',
5254               'webgpu-context-lost.html?query=kill_after_notification'),
5255+             ('ContextLost_WebGPUStressRequestDeviceAndRemoveLoop',
5256+              'webgpu-stress-request-device-and-remove-loop.html'),
5257              ('ContextLost_WebGLContextLostFromGPUProcessExit',
5258               'webgl.html?query=kill_after_notification'),
5259              ('ContextLost_WebGLContextLostFromLoseContextExtension',
5260@@ -339,6 +341,15 @@ class ContextLostIntegrationTest(gpu_integration_test.GpuIntegrationTest):
5261     self._KillGPUProcess(1, False, timeout=180)
5262     self._RestartBrowser('must restart after tests that kill the GPU process')
5263
5264+  def _ContextLost_WebGPUStressRequestDeviceAndRemoveLoop(self, test_path):
5265+    self.RestartBrowserIfNecessaryWithArgs([
5266+        '--enable-unsafe-webgpu',
5267+    ])
5268+    self._NavigateAndWaitForLoad(test_path)
5269+
5270+    # Test runs for 90 seconds; wait for 120 seconds.
5271+    self._WaitForTabAndCheckCompletion(timeout=120000)
5272+
5273   def _ContextLost_WebGLContextLostFromLoseContextExtension(self, test_path):
5274     self.RestartBrowserIfNecessaryWithArgs(
5275         [cba.DISABLE_DOMAIN_BLOCKING_FOR_3D_APIS])
5276diff --git a/content/web_test/browser/web_test_background_fetch_delegate.cc b/content/web_test/browser/web_test_background_fetch_delegate.cc
5277index c26c3bd236..befa7f1b50 100644
5278--- a/content/web_test/browser/web_test_background_fetch_delegate.cc
5279+++ b/content/web_test/browser/web_test_background_fetch_delegate.cc
5280@@ -293,6 +293,7 @@ void WebTestBackgroundFetchDelegate::DownloadUrl(
5281     const std::string& download_guid,
5282     const std::string& method,
5283     const GURL& url,
5284+    ::network::mojom::CredentialsMode credentials_mode,
5285     const net::NetworkTrafficAnnotationTag& traffic_annotation,
5286     const net::HttpRequestHeaders& headers,
5287     bool has_request_body) {
5288diff --git a/content/web_test/browser/web_test_background_fetch_delegate.h b/content/web_test/browser/web_test_background_fetch_delegate.h
5289index e307e86e32..106df11659 100644
5290--- a/content/web_test/browser/web_test_background_fetch_delegate.h
5291+++ b/content/web_test/browser/web_test_background_fetch_delegate.h
5292@@ -39,6 +39,7 @@ class WebTestBackgroundFetchDelegate : public BackgroundFetchDelegate {
5293                    const std::string& download_guid,
5294                    const std::string& method,
5295                    const GURL& url,
5296+                   ::network::mojom::CredentialsMode credentials_mode,
5297                    const net::NetworkTrafficAnnotationTag& traffic_annotation,
5298                    const net::HttpRequestHeaders& headers,
5299                    bool has_request_body) override;
5300diff --git a/device/fido/public_key_credential_descriptor.cc b/device/fido/public_key_credential_descriptor.cc
5301index 5c0328f855..bcda0c7659 100644
5302--- a/device/fido/public_key_credential_descriptor.cc
5303+++ b/device/fido/public_key_credential_descriptor.cc
5304@@ -4,6 +4,7 @@
5305
5306 #include <utility>
5307
5308+#include "device/fido/fido_transport_protocol.h"
5309 #include "device/fido/public_key_credential_descriptor.h"
5310
5311 namespace device {
5312@@ -13,6 +14,7 @@ namespace {
5313 // Keys for storing credential descriptor information in CBOR map.
5314 constexpr char kCredentialIdKey[] = "id";
5315 constexpr char kCredentialTypeKey[] = "type";
5316+constexpr char kTransportsKey[] = "transports";
5317
5318 }  // namespace
5319
5320@@ -33,8 +35,29 @@ PublicKeyCredentialDescriptor::CreateFromCBORValue(const cbor::Value& cbor) {
5321   if (id == map.end() || !id->second.is_bytestring())
5322     return base::nullopt;
5323
5324+  auto transports_it = map.find(cbor::Value(kTransportsKey));
5325+  if (transports_it == map.end())
5326+    return PublicKeyCredentialDescriptor(CredentialType::kPublicKey,
5327+                                         id->second.GetBytestring());
5328+
5329+  if (!transports_it->second.is_array())
5330+    return base::nullopt;
5331+
5332+  base::flat_set<FidoTransportProtocol> transports;
5333+  for (const cbor::Value& transport_name : transports_it->second.GetArray()) {
5334+    if (!transport_name.is_string()) {
5335+      return base::nullopt;
5336+    }
5337+    base::Optional<FidoTransportProtocol> transport =
5338+        ConvertToFidoTransportProtocol(transport_name.GetString());
5339+    if (!transport) {
5340+      continue;
5341+    }
5342+    transports.insert(*transport);
5343+  }
5344   return PublicKeyCredentialDescriptor(CredentialType::kPublicKey,
5345-                                       id->second.GetBytestring());
5346+                                       id->second.GetBytestring(),
5347+                                       std::move(transports));
5348 }
5349
5350 PublicKeyCredentialDescriptor::PublicKeyCredentialDescriptor() = default;
5351@@ -42,14 +65,7 @@ PublicKeyCredentialDescriptor::PublicKeyCredentialDescriptor() = default;
5352 PublicKeyCredentialDescriptor::PublicKeyCredentialDescriptor(
5353     CredentialType credential_type,
5354     std::vector<uint8_t> id)
5355-    : PublicKeyCredentialDescriptor(
5356-          credential_type,
5357-          std::move(id),
5358-          {FidoTransportProtocol::kUsbHumanInterfaceDevice,
5359-           FidoTransportProtocol::kBluetoothLowEnergy,
5360-           FidoTransportProtocol::kNearFieldCommunication,
5361-           FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy,
5362-           FidoTransportProtocol::kInternal}) {}
5363+    : PublicKeyCredentialDescriptor(credential_type, std::move(id), {}) {}
5364
5365 PublicKeyCredentialDescriptor::PublicKeyCredentialDescriptor(
5366     CredentialType credential_type,
5367@@ -84,6 +100,14 @@ cbor::Value AsCBOR(const PublicKeyCredentialDescriptor& desc) {
5368   cbor_descriptor_map[cbor::Value(kCredentialIdKey)] = cbor::Value(desc.id());
5369   cbor_descriptor_map[cbor::Value(kCredentialTypeKey)] =
5370       cbor::Value(CredentialTypeToString(desc.credential_type()));
5371+  std::vector<cbor::Value> transports;
5372+  for (FidoTransportProtocol transport : desc.transports()) {
5373+    transports.emplace_back(cbor::Value(ToString(transport)));
5374+  }
5375+  if (!transports.empty()) {
5376+    cbor_descriptor_map[cbor::Value(kTransportsKey)] =
5377+        cbor::Value(std::move(transports));
5378+  }
5379   return cbor::Value(std::move(cbor_descriptor_map));
5380 }
5381
5382diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
5383index e027b8fbc5..d4cd188452 100644
5384--- a/device/fido/virtual_ctap2_device.cc
5385+++ b/device/fido/virtual_ctap2_device.cc
5386@@ -965,6 +965,8 @@ base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnMakeCredential(
5387   }
5388   CtapMakeCredentialRequest request = std::move(*opt_request);
5389
5390+  mutable_state()->exclude_list_history.push_back(request.exclude_list);
5391+
5392   bool user_verified = false;
5393   const base::Optional<CtapDeviceResponseCode> uv_error = CheckUserVerification(
5394       /*is_make_credential=*/true, *device_info_, request.rp.id,
5395@@ -1222,7 +1224,7 @@ base::Optional<CtapDeviceResponseCode> VirtualCtap2Device::OnGetAssertion(
5396   }
5397   CtapGetAssertionRequest request = std::move(*opt_request);
5398
5399-  mutable_state()->allow_list_sizes.push_back(request.allow_list.size());
5400+  mutable_state()->allow_list_history.push_back(request.allow_list);
5401
5402   bool user_verified;
5403   const base::Optional<CtapDeviceResponseCode> uv_error = CheckUserVerification(
5404diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
5405index 4526c4786a..7a9aef82d3 100644
5406--- a/device/fido/virtual_fido_device.h
5407+++ b/device/fido/virtual_fido_device.h
5408@@ -21,6 +21,7 @@
5409 #include "device/fido/fido_constants.h"
5410 #include "device/fido/fido_device.h"
5411 #include "device/fido/fido_parsing_utils.h"
5412+#include "device/fido/public_key_credential_descriptor.h"
5413 #include "device/fido/public_key_credential_rp_entity.h"
5414 #include "device/fido/public_key_credential_user_entity.h"
5415 #include "net/cert/x509_util.h"
5416@@ -234,10 +235,16 @@ class COMPONENT_EXPORT(DEVICE_FIDO) VirtualFidoDevice : public FidoDevice {
5417     // to return from a previous authenticatorCredentialManagement command.
5418     std::list<cbor::Value::MapValue> pending_registrations;
5419
5420-    // allow_list_sizes contains the lengths of the allow_lists that have been
5421-    // seen in assertion requests. This is for tests to confirm that the
5422-    // expected sequence of requests was sent.
5423-    std::vector<size_t> allow_list_sizes;
5424+    // allow_list_history contains the allow_list values that have been seen in
5425+    // assertion requests. This is for tests to confirm that the expected
5426+    // sequence of requests was sent.
5427+    std::vector<std::vector<PublicKeyCredentialDescriptor>> allow_list_history;
5428+
5429+    // exclude_list_history contains the exclude_list values that have been seen
5430+    // in registration requests. This is for tests to confirm that the expected
5431+    // sequence of requests was sent.
5432+    std::vector<std::vector<PublicKeyCredentialDescriptor>>
5433+        exclude_list_history;
5434
5435     // The large-blob array.
5436     std::vector<uint8_t> large_blob;
5437diff --git a/device/gamepad/gamepad_monitor.cc b/device/gamepad/gamepad_monitor.cc
5438index 4a35a61d8b..9e1227f43d 100644
5439--- a/device/gamepad/gamepad_monitor.cc
5440+++ b/device/gamepad/gamepad_monitor.cc
5441@@ -54,6 +54,8 @@ void GamepadMonitor::GamepadStartPolling(GamepadStartPollingCallback callback) {
5442   GamepadService* service = GamepadService::GetInstance();
5443   if (!service->ConsumerBecameActive(this)) {
5444     mojo::ReportBadMessage("GamepadMonitor::GamepadStartPolling failed");
5445+    std::move(callback).Run(base::ReadOnlySharedMemoryRegion());
5446+    return;
5447   }
5448   std::move(callback).Run(service->DuplicateSharedMemoryRegion());
5449 }
5450diff --git a/extensions/browser/api/file_system/file_system_api.cc b/extensions/browser/api/file_system/file_system_api.cc
5451index 37d1f413ca..f047bc6c48 100644
5452--- a/extensions/browser/api/file_system/file_system_api.cc
5453+++ b/extensions/browser/api/file_system/file_system_api.cc
5454@@ -197,6 +197,9 @@ void PassFileInfoToUIThread(FileInfoOptCallback callback,
5455 content::WebContents* GetWebContentsForRenderFrameHost(
5456     content::BrowserContext* browser_context,
5457     content::RenderFrameHost* render_frame_host) {
5458+  if (!render_frame_host)
5459+    return nullptr;
5460+
5461   content::WebContents* web_contents =
5462       content::WebContents::FromRenderFrameHost(render_frame_host);
5463   // Check if there is an app window associated with the web contents; if not,
5464@@ -508,15 +511,6 @@ void FileSystemChooseEntryFunction::FilesSelected(
5465   }
5466
5467   if (is_directory_) {
5468-    // Get the WebContents for the app window to be the parent window of the
5469-    // confirmation dialog if necessary.
5470-    content::WebContents* const web_contents = GetWebContentsForRenderFrameHost(
5471-        browser_context(), render_frame_host());
5472-    if (!web_contents) {
5473-      Respond(Error(kInvalidCallingPage));
5474-      return;
5475-    }
5476-
5477     DCHECK_EQ(paths.size(), 1u);
5478     bool non_native_path = false;
5479 #if BUILDFLAG(IS_CHROMEOS_ASH)
5480@@ -530,7 +524,7 @@ void FileSystemChooseEntryFunction::FilesSelected(
5481         FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
5482         base::BindOnce(
5483             &FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this,
5484-            non_native_path, paths, web_contents));
5485+            non_native_path, paths));
5486     return;
5487   }
5488
5489@@ -543,8 +537,7 @@ void FileSystemChooseEntryFunction::FileSelectionCanceled() {
5490
5491 void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
5492     bool non_native_path,
5493-    const std::vector<base::FilePath>& paths,
5494-    content::WebContents* web_contents) {
5495+    const std::vector<base::FilePath>& paths) {
5496   const base::FilePath check_path =
5497       non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
5498   if (check_path.empty()) {
5499@@ -576,7 +569,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
5500         FROM_HERE,
5501         base::BindOnce(
5502             &FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
5503-            this, paths, web_contents));
5504+            this, paths));
5505     return;
5506   }
5507
5508@@ -587,8 +580,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
5509 }
5510
5511 void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
5512-    const std::vector<base::FilePath>& paths,
5513-    content::WebContents* web_contents) {
5514+    const std::vector<base::FilePath>& paths) {
5515   if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
5516     FileSelectionCanceled();
5517     return;
5518@@ -601,6 +593,13 @@ void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
5519     return;
5520   }
5521
5522+  content::WebContents* const web_contents =
5523+      GetWebContentsForRenderFrameHost(browser_context(), render_frame_host());
5524+  if (!web_contents) {
5525+    Respond(Error(kInvalidCallingPage));
5526+    return;
5527+  }
5528+
5529   delegate->ConfirmSensitiveDirectoryAccess(
5530       app_file_handler_util::HasFileSystemWritePermission(extension_.get()),
5531       base::UTF8ToUTF16(extension_->name()), web_contents,
5532diff --git a/extensions/browser/api/file_system/file_system_api.h b/extensions/browser/api/file_system/file_system_api.h
5533index ae1588ce85..0895a174a0 100644
5534--- a/extensions/browser/api/file_system/file_system_api.h
5535+++ b/extensions/browser/api/file_system/file_system_api.h
5536@@ -19,10 +19,6 @@
5537 #include "extensions/common/api/file_system.h"
5538 #include "ui/shell_dialogs/select_file_dialog.h"
5539
5540-namespace content {
5541-class WebContents;
5542-}  // namespace content
5543-
5544 namespace extensions {
5545 class ExtensionPrefs;
5546
5547@@ -168,13 +164,12 @@ class FileSystemChooseEntryFunction : public FileSystemEntryFunction {
5548   // directory. If so, calls ConfirmSensitiveDirectoryAccess. Otherwise, calls
5549   // OnDirectoryAccessConfirmed.
5550   void ConfirmDirectoryAccessAsync(bool non_native_path,
5551-                                   const std::vector<base::FilePath>& paths,
5552-                                   content::WebContents* web_contents);
5553+                                   const std::vector<base::FilePath>& paths);
5554
5555   // Shows a dialog to confirm whether the user wants to open the directory.
5556   // Calls OnDirectoryAccessConfirmed or FileSelectionCanceled.
5557-  void ConfirmSensitiveDirectoryAccess(const std::vector<base::FilePath>& paths,
5558-                                       content::WebContents* web_contents);
5559+  void ConfirmSensitiveDirectoryAccess(
5560+      const std::vector<base::FilePath>& paths);
5561
5562   void OnDirectoryAccessConfirmed(const std::vector<base::FilePath>& paths);
5563
5564diff --git a/extensions/renderer/messaging_util.cc b/extensions/renderer/messaging_util.cc
5565index f6bf874f98..7e9a0f124d 100644
5566--- a/extensions/renderer/messaging_util.cc
5567+++ b/extensions/renderer/messaging_util.cc
5568@@ -124,9 +124,13 @@ std::unique_ptr<Message> MessageFromJSONString(v8::Isolate* isolate,
5569     return nullptr;
5570   }
5571
5572-  bool has_transient_user_activation =
5573-      web_frame ? web_frame->HasTransientUserActivation() : false;
5574-  return std::make_unique<Message>(message, has_transient_user_activation,
5575+  // The message should carry user activation information only if the last
5576+  // activation in |web_frame| was triggered by a real user interaction.  See
5577+  // |UserActivationState::LastActivationWasRestricted()|.
5578+  bool has_unrestricted_user_activation =
5579+      web_frame && web_frame->HasTransientUserActivation() &&
5580+      !web_frame->LastActivationWasRestricted();
5581+  return std::make_unique<Message>(message, has_unrestricted_user_activation,
5582                                    privileged_context);
5583 }
5584
5585diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
5586index 1fc3b955bf..9e22317c68 100644
5587--- a/ipc/ipc_mojo_bootstrap.cc
5588+++ b/ipc/ipc_mojo_bootstrap.cc
5589@@ -931,10 +931,14 @@ class ChannelAssociatedGroupController
5590     if (!client)
5591       return;
5592
5593+    if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
5594+        !proxy_task_runner_->RunsTasksInCurrentSequence()) {
5595+      return;
5596+    }
5597+
5598     // Using client->interface_name() is safe here because this is a static
5599     // string defined for each mojo interface.
5600     TRACE_EVENT0("mojom", client->interface_name());
5601-    DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
5602
5603     // Sync messages should never make their way to this method.
5604     DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
5605@@ -965,10 +969,15 @@ class ChannelAssociatedGroupController
5606     if (!client)
5607       return;
5608
5609+    if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
5610+        !proxy_task_runner_->RunsTasksInCurrentSequence()) {
5611+      return;
5612+    }
5613+
5614     // Using client->interface_name() is safe here because this is a static
5615     // string defined for each mojo interface.
5616     TRACE_EVENT0("mojom", client->interface_name());
5617-    DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence());
5618+
5619     MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
5620
5621     // The message must have already been dequeued by the endpoint waking up
5622diff --git a/media/base/ohos/ohos_media_player_bridge.cc b/media/base/ohos/ohos_media_player_bridge.cc
5623index 882a855a4c..e2c6cab24b 100644
5624--- a/media/base/ohos/ohos_media_player_bridge.cc
5625+++ b/media/base/ohos/ohos_media_player_bridge.cc
5626@@ -139,9 +139,9 @@ void OHOSMediaPlayerBridge::FinishPaint(int fd) {
5627     return;
5628   }
5629
5630-  if (cached_buffers_.front()->GetBufferHandle()->reserve[0] != fd) {
5631+  if (cached_buffers_.front()->GetBufferHandle()->fd != fd) {
5632     LOG(ERROR) << "match fd error render fd=" << fd << "  browser fd="
5633-               << cached_buffers_.front()->GetBufferHandle()->reserve[0];
5634+               << cached_buffers_.front()->GetBufferHandle()->fd;
5635   }
5636   OHOS::SurfaceError ret =
5637       consumer_surface_->ReleaseBuffer(cached_buffers_.front(), -1);
5638@@ -187,9 +187,31 @@ void OHOSMediaPlayerBridge::OnBufferAvailable(
5639                        weak_factory_.GetWeakPtr(), std::move(buffer)));
5640     return;
5641   }
5642-  client_->OnFrameAvailable(buffer->GetBufferHandle()->reserve[0],
5643-                            buffer->GetSize(), buffer->GetWidth(),
5644-                            buffer->GetHeight());
5645+
5646+  // int32_t coded_height;
5647+  // int32_t coded_width;
5648+
5649+  // // video frame height must be 32*N
5650+  // const int step_height = 32;
5651+  // // argb format video frame should divided by 4
5652+  // const int argb_stride_step = 4;
5653+  // if (buffer->GetHeight() % step_height == 0) {
5654+  //   coded_height = buffer->GetHeight();
5655+  // } else {
5656+  //   coded_height = (buffer->GetHeight() / step_height + 1) * step_height;
5657+  // }
5658+  // if (buffer->GetFormat() == PIXEL_FMT_RGBA_8888) {
5659+  //   coded_width = buffer->GetStride() / argb_stride_step;
5660+  // } else {
5661+  //   coded_width = buffer->GetStride();
5662+  // }
5663+  if (buffer->GetBufferHandle()->fd <= 0) {
5664+    LOG(ERROR)<<"Unavailble fd frome meidaplayer";
5665+  }
5666+  client_->OnFrameAvailable(buffer->GetBufferHandle()->fd,
5667+                            buffer->GetSize(), buffer->GetWidth(), buffer->GetHeight(),
5668+                            buffer->GetWidth(), buffer->GetHeight(),
5669+                            buffer->GetFormat());
5670   cached_buffers_.push_back(buffer);
5671 }
5672
5673diff --git a/media/base/ohos/ohos_media_player_bridge.h b/media/base/ohos/ohos_media_player_bridge.h
5674index 2446a5dec1..631af9c93e 100644
5675--- a/media/base/ohos/ohos_media_player_bridge.h
5676+++ b/media/base/ohos/ohos_media_player_bridge.h
5677@@ -22,8 +22,11 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge {
5678    public:
5679     virtual void OnFrameAvailable(int fd,
5680                                   uint32_t size,
5681-                                  int32_t width,
5682-                                  int32_t height) = 0;
5683+                                  int32_t coded_width,
5684+                                  int32_t coded_height,
5685+                                  int32_t visible_width,
5686+                                  int32_t visible_height,
5687+                                  int32_t format) = 0;
5688
5689     // Called when media duration is first detected or changes.
5690     virtual void OnMediaDurationChanged(base::TimeDelta duration) = 0;
5691@@ -73,7 +76,6 @@ class MEDIA_EXPORT OHOSMediaPlayerBridge {
5692   void OnPlayerStateUpdate(OHOS::Media::PlayerStates player_state);
5693
5694  private:
5695-
5696   int32_t SetFdSource(const std::string& path);
5697
5698   const std::string surfaceFormat = "SURFACE_FORMAT";
5699diff --git a/media/base/ohos/ohos_media_player_listener.cc b/media/base/ohos/ohos_media_player_listener.cc
5700index bb08070c17..5e2e5db877 100644
5701--- a/media/base/ohos/ohos_media_player_listener.cc
5702+++ b/media/base/ohos/ohos_media_player_listener.cc
5703@@ -4,6 +4,7 @@
5704
5705 #include "media/base/ohos/ohos_media_player_listener.h"
5706
5707+#include <display_type.h>
5708 namespace media {
5709
5710 OHOSMediaPlayerListener::OHOSMediaPlayerListener(
5711@@ -32,9 +33,16 @@ void OHOSMediaPlayerListener::OnBufferAvailable() {
5712     LOG(ERROR) << "acquire buffer fail, ret=" << ret;
5713     return;
5714   }
5715-  task_runner_->PostTask(
5716-      FROM_HERE, base::BindOnce(&OHOSMediaPlayerBridge::OnBufferAvailable,
5717-                                media_player_, buffer));
5718+
5719+  if (buffer->GetFormat() == PIXEL_FMT_RGBA_8888 ||
5720+      buffer->GetFormat() == PIXEL_FMT_YCBCR_420_SP) {
5721+    task_runner_->PostTask(
5722+        FROM_HERE, base::BindOnce(&OHOSMediaPlayerBridge::OnBufferAvailable,
5723+                                  media_player_, buffer));
5724+  } else {
5725+    LOG(ERROR) << "Unsupport format for:" << buffer->GetFormat();
5726+    surface_temp->ReleaseBuffer(buffer, -1);
5727+  }
5728 }
5729
5730 }  // namespace media
5731diff --git a/media/mojo/mojom/renderer_extensions.mojom b/media/mojo/mojom/renderer_extensions.mojom
5732index 8d8e58cda5..07bd82171d 100644
5733--- a/media/mojo/mojom/renderer_extensions.mojom
5734+++ b/media/mojo/mojom/renderer_extensions.mojom
5735@@ -13,8 +13,11 @@ import "ui/gfx/geometry/mojom/geometry.mojom";
5736 struct OhosSurfaceBufferHandle {
5737   uint32 buffer_size;
5738   int32 fd_browser;
5739-  int32 width;
5740-  int32 height;
5741+  int32 coded_width;
5742+  int32 coded_height;
5743+  int32 visible_width;
5744+  int32 visible_height;
5745+  int32 format;
5746   handle<platform> buffer_fd;
5747 };
5748
5749diff --git a/mojo/core/handle_table.cc b/mojo/core/handle_table.cc
5750index 9426281d73..a044f1c8e3 100644
5751--- a/mojo/core/handle_table.cc
5752+++ b/mojo/core/handle_table.cc
5753@@ -65,13 +65,19 @@ bool HandleTable::AddDispatchersFromTransit(
5754     const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
5755     MojoHandle* handles) {
5756   // Oops, we're out of handles.
5757-  if (next_available_handle_ == MOJO_HANDLE_INVALID)
5758+  if (next_available_handle_ == MOJO_HANDLE_INVALID) {
5759     return false;
5760+  }
5761+
5762+  // MOJO_HANDLE_INVALID is zero.
5763+  DCHECK_GE(next_available_handle_, 1u);
5764
5765-  DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
5766   // If this insertion would cause handle overflow, we're out of handles.
5767-  if (next_available_handle_ + dispatchers.size() < next_available_handle_)
5768+  const uint32_t num_handles_available =
5769+      std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
5770+  if (num_handles_available < dispatchers.size()) {
5771     return false;
5772+  }
5773
5774   for (size_t i = 0; i < dispatchers.size(); ++i) {
5775     MojoHandle handle = MOJO_HANDLE_INVALID;
5776diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md
5777index 05581aa626..d3ecb7e55a 100644
5778--- a/mojo/public/cpp/bindings/README.md
5779+++ b/mojo/public/cpp/bindings/README.md
5780@@ -1709,6 +1709,9 @@ C++ sources can depend on shared sources only, by referencing the
5781 `"${target_name}_shared"` target, e.g. `"//foo/mojom:mojom_shared"` in the
5782 example above.
5783
5784+For converting between Blink and non-Blink variants, please see
5785+`//third_party/blink/public/platform/cross_variant_mojo_util.h`.
5786+
5787 ## Versioning Considerations
5788
5789 For general documentation of versioning in the Mojom IDL see
5790diff --git a/mojo/public/cpp/bindings/lib/message_fragment.h b/mojo/public/cpp/bindings/lib/message_fragment.h
5791index 226c364468..b380da4131 100644
5792--- a/mojo/public/cpp/bindings/lib/message_fragment.h
5793+++ b/mojo/public/cpp/bindings/lib/message_fragment.h
5794@@ -149,8 +149,7 @@ class MessageFragment<Array_Data<T>> {
5795     static_assert(
5796         std::numeric_limits<uint32_t>::max() > Traits::kMaxNumElements,
5797         "Max num elements castable to 32bit");
5798-    if (num_elements > Traits::kMaxNumElements)
5799-      return;
5800+    CHECK_LE(num_elements, Traits::kMaxNumElements);
5801
5802     const uint32_t num_bytes =
5803         Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
5804diff --git a/net/BUILD.gn b/net/BUILD.gn
5805index edc7e8f38d..6232aeac47 100644
5806--- a/net/BUILD.gn
5807+++ b/net/BUILD.gn
5808@@ -1688,6 +1688,7 @@ source_set("net_deps") {
5809
5810   public_deps = [
5811     ":constants",
5812+    ":isolation_info_proto",
5813     ":net_export_header",
5814     ":net_resources",
5815     ":preload_decoder",
5816@@ -1805,6 +1806,10 @@ proto_library("net_nqe_proto") {
5817   extra_configs = [ "//build/config/compiler:wexit_time_destructors" ]
5818 }
5819
5820+proto_library("isolation_info_proto") {
5821+  sources = [ "base/isolation_info.proto" ]
5822+}
5823+
5824 component("extras") {
5825   sources = [
5826     "extras/sqlite/cookie_crypto_delegate.h",
5827diff --git a/net/base/isolation_info.cc b/net/base/isolation_info.cc
5828index e51644b222..3eb150b577 100644
5829--- a/net/base/isolation_info.cc
5830+++ b/net/base/isolation_info.cc
5831@@ -5,6 +5,7 @@
5832 #include "net/base/isolation_info.h"
5833
5834 #include "base/check_op.h"
5835+#include "net/base/isolation_info.pb.h"
5836
5837 namespace net {
5838
5839@@ -126,6 +127,35 @@ IsolationInfo IsolationInfo::CreateOpaqueAndNonTransient() {
5840                        base::nullopt /* party_context */);
5841 }
5842
5843+base::Optional<IsolationInfo> IsolationInfo::Deserialize(
5844+    const std::string& serialized) {
5845+  proto::IsolationInfo proto;
5846+  if (!proto.ParseFromString(serialized))
5847+    return base::nullopt;
5848+
5849+  base::Optional<url::Origin> top_frame_origin;
5850+  if (proto.has_top_frame_origin())
5851+    top_frame_origin = url::Origin::Create(GURL(proto.top_frame_origin()));
5852+
5853+  base::Optional<url::Origin> frame_origin;
5854+  if (proto.has_frame_origin())
5855+    frame_origin = url::Origin::Create(GURL(proto.frame_origin()));
5856+
5857+  base::Optional<std::set<SchemefulSite>> party_context;
5858+  if (proto.has_party_context()) {
5859+    party_context = std::set<SchemefulSite>();
5860+    for (const auto& site : proto.party_context().site()) {
5861+      party_context->insert(SchemefulSite::Deserialize(site));
5862+    }
5863+  }
5864+
5865+  return IsolationInfo::CreateIfConsistent(
5866+      static_cast<RequestType>(proto.request_type()),
5867+      std::move(top_frame_origin), std::move(frame_origin),
5868+      SiteForCookies::FromUrl(GURL(proto.site_for_cookies())),
5869+      false /* opaque_and_non_transient */, std::move(party_context));
5870+}
5871+
5872 IsolationInfo IsolationInfo::Create(
5873     RequestType request_type,
5874     const url::Origin& top_frame_origin,
5875@@ -219,6 +249,35 @@ IsolationInfo IsolationInfo::ToDoUseTopFrameOriginAsWell(
5876       std::set<SchemefulSite>() /* party_context */);
5877 }
5878
5879+std::string IsolationInfo::Serialize() const {
5880+  if (network_isolation_key().IsTransient())
5881+    return "";
5882+
5883+  if (opaque_and_non_transient_)
5884+    return "";
5885+
5886+  proto::IsolationInfo info;
5887+
5888+  info.set_request_type(static_cast<int32_t>(request_type_));
5889+
5890+  if (top_frame_origin_)
5891+    info.set_top_frame_origin(top_frame_origin_->Serialize());
5892+
5893+  if (frame_origin_)
5894+    info.set_frame_origin(frame_origin_->Serialize());
5895+
5896+  info.set_site_for_cookies(site_for_cookies_.RepresentativeUrl().spec());
5897+
5898+  if (party_context_) {
5899+    auto* pc = info.mutable_party_context();
5900+    for (const auto& site : *party_context_) {
5901+      pc->add_site(site.Serialize());
5902+    }
5903+  }
5904+
5905+  return info.SerializeAsString();
5906+}
5907+
5908 IsolationInfo::IsolationInfo(
5909     RequestType request_type,
5910     const base::Optional<url::Origin>& top_frame_origin,
5911diff --git a/net/base/isolation_info.h b/net/base/isolation_info.h
5912index 28d6b1c7f7..f33bd4bb99 100644
5913--- a/net/base/isolation_info.h
5914+++ b/net/base/isolation_info.h
5915@@ -6,6 +6,7 @@
5916 #define NET_BASE_ISOLATION_INFO_H_
5917
5918 #include <set>
5919+#include <string>
5920
5921 #include "base/optional.h"
5922 #include "net/base/net_export.h"
5923@@ -96,6 +97,11 @@ class NET_EXPORT IsolationInfo {
5924   // allows use of the disk cache with a transient NIK.
5925   static IsolationInfo CreateOpaqueAndNonTransient();
5926
5927+  // Creates an IsolationInfo from the serialized contents. Returns a nullopt
5928+  // if deserialization fails or if data is inconsistent.
5929+  static base::Optional<IsolationInfo> Deserialize(
5930+      const std::string& serialized);
5931+
5932   // Creates an IsolationInfo with the provided parameters. If the parameters
5933   // are inconsistent, DCHECKs. In particular:
5934   // * If |request_type| is kMainFrame, |top_frame_origin| must equal
5935@@ -198,6 +204,10 @@ class NET_EXPORT IsolationInfo {
5936
5937   bool IsEqualForTesting(const IsolationInfo& other) const;
5938
5939+  // Serialize the `IsolationInfo` into a string. Fails if transient, returning
5940+  // an empty string.
5941+  std::string Serialize() const;
5942+
5943  private:
5944   IsolationInfo(RequestType request_type,
5945                 const base::Optional<url::Origin>& top_frame_origin,
5946diff --git a/net/base/isolation_info.proto b/net/base/isolation_info.proto
5947new file mode 100644
5948index 0000000000..252b738245
5949--- /dev/null
5950+++ b/net/base/isolation_info.proto
5951@@ -0,0 +1,19 @@
5952+// Copyright 2021 The Chromium Authors. All rights reserved.
5953+// Use of this source code is governed by a BSD-style license that can be
5954+// found in the LICENSE file.
5955+
5956+syntax = "proto2";
5957+
5958+option optimize_for = LITE_RUNTIME;
5959+
5960+package net.proto;
5961+
5962+message IsolationInfo {
5963+  optional int32 request_type = 1;  // net::IsolationInfo::RequestType
5964+  optional string top_frame_origin = 2;
5965+  optional string frame_origin = 3;
5966+  optional string site_for_cookies = 4;
5967+
5968+  message PartyContext { repeated string site = 1; }
5969+  optional PartyContext party_context = 5;
5970+}
5971\ No newline at end of file
5972diff --git a/net/base/isolation_info_unittest.cc b/net/base/isolation_info_unittest.cc
5973index 5c6461ea6b..bf8cd296ca 100644
5974--- a/net/base/isolation_info_unittest.cc
5975+++ b/net/base/isolation_info_unittest.cc
5976@@ -48,6 +48,9 @@ class IsolationInfoTest : public testing::Test {
5977       std::set<net::SchemefulSite>{net::SchemefulSite(kOrigin2)};
5978   const base::Optional<std::set<net::SchemefulSite>> kPartyContext3 =
5979       std::set<net::SchemefulSite>{net::SchemefulSite(kOrigin3)};
5980+  const base::Optional<std::set<net::SchemefulSite>> kPartyContextMultiple =
5981+      std::set<net::SchemefulSite>{net::SchemefulSite(kOrigin1),
5982+                                   net::SchemefulSite(kOrigin2)};
5983 };
5984
5985 TEST_F(IsolationInfoTest, RequestTypeMainFrame) {
5986@@ -502,6 +505,62 @@ TEST_F(IsolationInfoTest, CreateForRedirectPartyContext) {
5987   }
5988 }
5989
5990+TEST_F(IsolationInfoTest, Serialization) {
5991+  EXPECT_FALSE(IsolationInfo::Deserialize(""));
5992+  EXPECT_FALSE(IsolationInfo::Deserialize("garbage"));
5993+
5994+  const IsolationInfo kPositiveTestCases[] = {
5995+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
5996+                            kOrigin2, SiteForCookies::FromOrigin(kOrigin1),
5997+                            kPartyContext1),
5998+      // Null party context
5999+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6000+                            kOrigin2, SiteForCookies::FromOrigin(kOrigin1),
6001+                            kPartyContextNull),
6002+      // Empty party context
6003+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6004+                            kOrigin2, SiteForCookies::FromOrigin(kOrigin1),
6005+                            kPartyContextEmpty),
6006+      // Multiple party context entries.
6007+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6008+                            kOrigin2, SiteForCookies::FromOrigin(kOrigin1),
6009+                            kPartyContextMultiple),
6010+      // Without SiteForCookies
6011+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6012+                            kOrigin2, SiteForCookies(), base::nullopt),
6013+      // Request type kOther
6014+      IsolationInfo::Create(IsolationInfo::RequestType::kOther, kOrigin1,
6015+                            kOrigin1, SiteForCookies::FromOrigin(kOrigin1),
6016+                            base::nullopt),
6017+      // Request type kMainframe
6018+      IsolationInfo::Create(IsolationInfo::RequestType::kMainFrame, kOrigin1,
6019+                            kOrigin1, SiteForCookies::FromOrigin(kOrigin1),
6020+                            base::nullopt),
6021+  };
6022+  for (const auto& info : kPositiveTestCases) {
6023+    auto rt = IsolationInfo::Deserialize(info.Serialize());
6024+    ASSERT_TRUE(rt);
6025+    EXPECT_TRUE(rt->IsEqualForTesting(info));
6026+  }
6027+
6028+  const IsolationInfo kNegativeTestCases[] = {
6029+      IsolationInfo::CreateTransient(),
6030+      IsolationInfo::CreateOpaqueAndNonTransient(),
6031+      // With nonce (i.e transient).
6032+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6033+                            kOrigin2, SiteForCookies::FromOrigin(kOrigin1),
6034+                            kPartyContext1, &kNonce1),
6035+      // With an opaque origin (i.e transient)
6036+      IsolationInfo::Create(IsolationInfo::RequestType::kSubFrame, kOrigin1,
6037+                            url::Origin(), SiteForCookies::FromOrigin(kOrigin1),
6038+                            base::nullopt),
6039+
6040+  };
6041+  for (const auto& info : kNegativeTestCases) {
6042+    EXPECT_TRUE(info.Serialize().empty());
6043+  }
6044+}
6045+
6046 }  // namespace
6047
6048 }  // namespace net
6049diff --git a/net/cert/cert_verify_proc_ohos.cc b/net/cert/cert_verify_proc_ohos.cc
6050index b36b8d9022..82d219d37d 100644
6051--- a/net/cert/cert_verify_proc_ohos.cc
6052+++ b/net/cert/cert_verify_proc_ohos.cc
6053@@ -3,9 +3,19 @@
6054 // found in the LICENSE file.
6055
6056 #include "net/cert/cert_verify_proc_ohos.h"
6057-
6058+#include <string>
6059+#include <vector>
6060+#include "base/logging.h"
6061 #include "net/cert/cert_net_fetcher.h"
6062+#include "net/cert/x509_certificate.h"
6063+#include "net/cert/x509_util.h"
6064+#include "openssl/err.h"
6065+#include "openssl/ossl_typ.h"
6066+#include "openssl/x509.h"
6067+#include "openssl/x509_vfy.h"
6068
6069+#define ROOT_CERT "/etc/ssl/certs/cacert.pem"
6070+#define MIN_CERT_NUM 1
6071 namespace net {
6072 CertVerifyProcOHOS::CertVerifyProcOHOS(
6073     scoped_refptr<CertNetFetcher> cert_net_fetcher)
6074@@ -17,6 +27,131 @@ bool CertVerifyProcOHOS::SupportsAdditionalTrustAnchors() const {
6075   return false;
6076 }
6077
6078+void GetChainDEREncodedBytes(X509Certificate* cert,
6079+                             std::vector<std::string>* chain_bytes) {
6080+  chain_bytes->reserve(1 + cert->intermediate_buffers().size());
6081+  chain_bytes->emplace_back(
6082+      net::x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()));
6083+  for (const auto& handle : cert->intermediate_buffers()) {
6084+    chain_bytes->emplace_back(
6085+        net::x509_util::CryptoBufferAsStringPiece(handle.get()));
6086+  }
6087+}
6088+
6089+void X509_d2i_free(X509* server_cert[], uint32_t server_cert_sum) {
6090+  uint32_t i;
6091+  for (i = 0; i < server_cert_sum; i++) {
6092+    X509_free(server_cert[i]);
6093+  }
6094+}
6095+
6096+bool CertChainVerify(X509* server_cert[],
6097+                     uint32_t server_cert_sum,
6098+                     X509_STORE* root_store) {
6099+  uint32_t i;
6100+  STACK_OF(X509)* ca_stack = nullptr;
6101+  X509_STORE_CTX* ctx = nullptr;
6102+
6103+  // certificate chain verify
6104+  for (i = server_cert_sum - 1; i > 0; i--) {
6105+    // Create certificate store context function
6106+    ctx = X509_STORE_CTX_new();
6107+    if (ctx == nullptr) {
6108+      LOG(ERROR) << "Create certificate store context function failed";
6109+      X509_d2i_free(server_cert, server_cert_sum);
6110+      X509_STORE_free(root_store);
6111+      return false;
6112+    }
6113+
6114+    // Initialize the certificate chain
6115+    X509_STORE_CTX_init(ctx, root_store, server_cert[i], ca_stack);
6116+
6117+    // If verification fails, for detailed error information, see
6118+    // X509_verify_cert_error_string
6119+    if (!X509_verify_cert(ctx)) {
6120+      LOG(ERROR) << "Certificate verify error: " << ctx->error
6121+                 << "\nCertificate verify info: "
6122+                 << X509_verify_cert_error_string(ctx->error)
6123+                 << "\nTotal number of server certificates: " << server_cert_sum
6124+                 << "\nserver certificates count: " << i;
6125+      X509_d2i_free(server_cert, server_cert_sum);
6126+      X509_STORE_CTX_free(ctx);
6127+      X509_STORE_free(root_store);
6128+      return false;
6129+    }
6130+
6131+    X509_STORE_CTX_free(ctx);
6132+  }
6133+
6134+  X509_d2i_free(server_cert, server_cert_sum);
6135+  X509_STORE_free(root_store);
6136+
6137+  return true;
6138+}
6139+
6140+bool CertVerify(std::vector<std::string>& cert_bytes) {
6141+  uint32_t server_cert_sum;
6142+  const unsigned char* der_encoded_tmp = nullptr;
6143+  uint32_t i;
6144+  int root_cert_sum = 0;
6145+  X509_STORE* root_store = nullptr;
6146+  X509_LOOKUP* look_up = nullptr;
6147+
6148+  server_cert_sum = cert_bytes.size();
6149+  if (server_cert_sum < MIN_CERT_NUM) {
6150+    LOG(ERROR) << "Total number of server certificates is error";
6151+    return false;
6152+  }
6153+
6154+  // Convert cert_bytes to internal X509 data structure(server_cert[]), If the
6155+  // conversion fails, see ERR_reason_error_string()/kLibraryNames
6156+  X509* server_cert[server_cert_sum];
6157+  for (i = 0; i < server_cert_sum; i++) {
6158+    der_encoded_tmp = (unsigned char*)cert_bytes[i].c_str();
6159+    server_cert[i] = d2i_X509(nullptr, &der_encoded_tmp, cert_bytes[i].size());
6160+    if (server_cert[i] == nullptr) {
6161+      LOG(ERROR)
6162+          << "Server certificate DEREncoded converted to X509 error, Reason: "
6163+          << ERR_reason_error_string(ERR_get_error())
6164+          << "\nTotal number of server certificates: " << server_cert_sum
6165+          << "\nError certificate count:" << i;
6166+      ERR_clear_error();
6167+      X509_d2i_free(server_cert, i);
6168+      return false;
6169+    }
6170+  }
6171+
6172+  // Create X509 certificate store
6173+  root_store = X509_STORE_new();
6174+  if (root_store == nullptr) {
6175+    LOG(ERROR) << "Create X509 certificate store failed";
6176+    X509_d2i_free(server_cert, server_cert_sum);
6177+    return false;
6178+  }
6179+
6180+  // Create X509_LOOKUP, the store_ctx member of this data structure is
6181+  // associated with the newly created certificate store root_store
6182+  look_up = X509_STORE_add_lookup(root_store, X509_LOOKUP_file());
6183+  if (look_up == nullptr) {
6184+    LOG(ERROR) << "Create X509 LOOKUP failed";
6185+    X509_d2i_free(server_cert, server_cert_sum);
6186+    X509_STORE_free(root_store);
6187+    return false;
6188+  }
6189+
6190+  // Parse the root certificate file
6191+  root_cert_sum =
6192+      X509_load_cert_crl_file(look_up, ROOT_CERT, X509_FILETYPE_PEM);
6193+  if (root_cert_sum == 0) {
6194+    LOG(ERROR) << "Root certificate number is 0";
6195+    X509_d2i_free(server_cert, server_cert_sum);
6196+    X509_STORE_free(root_store);
6197+    return false;
6198+  }
6199+
6200+  return CertChainVerify(server_cert, server_cert_sum, root_store);
6201+}
6202+
6203 int CertVerifyProcOHOS::VerifyInternal(
6204     X509Certificate* cert,
6205     const std::string& hostname,
6206@@ -27,7 +162,14 @@ int CertVerifyProcOHOS::VerifyInternal(
6207     const CertificateList& additional_trust_anchors,
6208     CertVerifyResult* verify_result,
6209     const NetLogWithSource& net_log) {
6210-  //TODO: no implement
6211+  std::vector<std::string> cert_bytes;
6212+
6213+  GetChainDEREncodedBytes(cert, &cert_bytes);
6214+
6215+  if (!CertVerify(cert_bytes)) {
6216+    return ERR_FAILED;
6217+  }
6218+
6219   return OK;
6220 }
6221
6222diff --git a/ohos_nweb/BUILD.gn b/ohos_nweb/BUILD.gn
6223index c87c2a462f..aa77be3230 100644
6224--- a/ohos_nweb/BUILD.gn
6225+++ b/ohos_nweb/BUILD.gn
6226@@ -181,10 +181,28 @@ executable("web_render") {
6227   sources = [
6228     "src/ohos_nweb_main.cc",
6229   ]
6230+  deps = [
6231+    ":nweb_hilog",
6232+  ]
6233+}
6234+
6235+shared_library("libnweb_render") {
6236+  defines = [
6237+    "OHOS_NWEB",
6238+  ]
6239+
6240+  include_dirs = [
6241+    "include",
6242+  ]
6243+  include_dirs += ohos_src_includes
6244+
6245+  sources = [
6246+    "src/nweb_render_main.cc",
6247+  ]
6248
6249   deps = [
6250     ":nweb_hilog",
6251     "//cef:libweb_engine",
6252     "//cef:libcef_dll_wrapper",
6253   ]
6254-}
6255\ No newline at end of file
6256+}
6257diff --git a/ohos_nweb/include/nweb.h b/ohos_nweb/include/nweb.h
6258index 707d3a6fd8..10c2f66e40 100755
6259--- a/ohos_nweb/include/nweb.h
6260+++ b/ohos_nweb/include/nweb.h
6261@@ -150,7 +150,7 @@ class OHOS_NWEB_EXPORT NWeb : public std::enable_shared_from_this<NWeb> {
6262      *
6263      * @return the last HitTestResult
6264      */
6265-     virtual const HitTestResult GetHitTestResult() const = 0;
6266+     virtual HitTestResult GetHitTestResult() const = 0;
6267
6268     /**
6269      * Sets the background color for this view.
6270diff --git a/ohos_nweb/include/nweb_access_request.h b/ohos_nweb/include/nweb_access_request.h
6271index 853c91ec86..6592ba26ee 100644
6272--- a/ohos_nweb/include/nweb_access_request.h
6273+++ b/ohos_nweb/include/nweb_access_request.h
6274@@ -11,47 +11,47 @@
6275
6276 namespace OHOS::NWeb {
6277 class OHOS_NWEB_EXPORT NWebAccessRequest {
6278- public:
6279-  NWebAccessRequest() = default;
6280-
6281-  virtual ~NWebAccessRequest() = default;
6282-
6283-  enum Resources {
6284-    GEOLOCATION = 1 << 0,
6285-    VIDEO_CAPTURE = 1 << 1,
6286-    AUDIO_CAPTURE = 1 << 2,
6287-    PROTECTED_MEDIA_ID = 1 << 3,
6288-    MIDI_SYSEX = 1 << 4,
6289-  };
6290-
6291-  /**
6292-   * Get the origin of the web page which is trying to access the resource.
6293-   *
6294-   * @return the origin of the web page which is trying to access the resource.
6295-   */
6296-  virtual std::string Origin() = 0;
6297-
6298-  /**
6299-   * Get the resource id the web page is trying to access.
6300-   *
6301-   * @return the resource id the web page is trying to access.
6302-   */
6303-  virtual int ResourceAcessId() = 0;
6304-
6305-  /**
6306-   * Agree the origin to access the given resources.
6307-   * The granted access is only valid for this WebView.
6308-   *
6309-   * @param resourceId id of the resource agreed to be accessed by origin. It
6310-   * must be equal to requested resource id returned by {@link
6311-   * #GetResourceAcessId()}.
6312-   */
6313-  virtual void Agree(int resourceId) = 0;
6314-
6315-  /**
6316-   * Refuse the request.
6317-   */
6318-  virtual void Refuse() = 0;
6319+public:
6320+    NWebAccessRequest() = default;
6321+
6322+    virtual ~NWebAccessRequest() = default;
6323+
6324+    enum Resources {
6325+        GEOLOCATION = 1 << 0,
6326+        VIDEO_CAPTURE = 1 << 1,
6327+        AUDIO_CAPTURE = 1 << 2,
6328+        PROTECTED_MEDIA_ID = 1 << 3,
6329+        MIDI_SYSEX = 1 << 4,
6330+    };
6331+
6332+    /**
6333+    * Get the origin of the web page which is trying to access the resource.
6334+    *
6335+    * @return the origin of the web page which is trying to access the resource.
6336+    */
6337+    virtual std::string Origin() = 0;
6338+
6339+    /**
6340+    * Get the resource id the web page is trying to access.
6341+    *
6342+    * @return the resource id the web page is trying to access.
6343+    */
6344+    virtual int ResourceAcessId() = 0;
6345+
6346+    /**
6347+    * Agree the origin to access the given resources.
6348+    * The granted access is only valid for this WebView.
6349+    *
6350+    * @param resourceId id of the resource agreed to be accessed by origin. It
6351+    * must be equal to requested resource id returned by {@link
6352+    * #GetResourceAcessId()}.
6353+    */
6354+    virtual void Agree(int resourceId) = 0;
6355+
6356+    /**
6357+    * Refuse the request.
6358+    */
6359+    virtual void Refuse() = 0;
6360 };
6361 }  // namespace OHOS::NWeb
6362
6363diff --git a/ohos_nweb/include/nweb_console_log.h b/ohos_nweb/include/nweb_console_log.h
6364index 2089061420..b0a8d6bbd9 100644
6365--- a/ohos_nweb/include/nweb_console_log.h
6366+++ b/ohos_nweb/include/nweb_console_log.h
6367@@ -76,4 +76,4 @@ private:
6368 };
6369 }
6370
6371-#endif
6372\ No newline at end of file
6373+#endif // NWEB_CONSOLE_LOG_H
6374\ No newline at end of file
6375diff --git a/ohos_nweb/include/nweb_cookie_manager.h b/ohos_nweb/include/nweb_cookie_manager.h
6376index 11800d8579..4e2c33aaf9 100644
6377--- a/ohos_nweb/include/nweb_cookie_manager.h
6378+++ b/ohos_nweb/include/nweb_cookie_manager.h
6379@@ -31,7 +31,6 @@ public:
6380      * @return true if the instance send and accept cookies.
6381      */
6382     virtual bool IsAcceptCookieAllowed() const = 0;
6383-
6384     /**
6385      * @brief Sets whether the instance should send and accept cookies.
6386      * By default this is set to true and the nweb accepts cookies.
6387@@ -39,21 +38,18 @@ public:
6388      * @param accept whether the instance should send and accept cookies.
6389      */
6390     virtual void PutAcceptCookieEnabled(bool accept) = 0;
6391-
6392     /**
6393      * @brief Get whether instances can send and accept cookies for file scheme URLs.
6394      *
6395      * @return true if instances send and accept cookies for file scheme URLs.
6396      */
6397     virtual bool IsFileURLSchemeCookiesAllowed() const = 0;
6398-
6399     /**
6400      * @brief Sets whether the instance should send and accept cookies for file scheme URLs.
6401      *
6402      * @param allow whether the instance should send and accept cookies for file scheme URLs.
6403      */
6404     virtual void PutAcceptFileURLSchemeCookiesEnabled(bool allow) = 0;
6405-
6406     /**
6407      * @brief Gets all the cookies for the given URL.
6408      *
6409@@ -62,7 +58,6 @@ public:
6410      */
6411     virtual void ReturnCookie(const std::string &url,
6412                               std::shared_ptr<NWebValueCallback<std::string>> callback) = 0;
6413-
6414     /**
6415      * @brief GSets a single cookie (key-value pair) for the given URL.
6416      *
6417@@ -73,14 +68,12 @@ public:
6418     virtual void SetCookie(const std::string &url,
6419                            const std::string &value,
6420                            std::shared_ptr<NWebValueCallback<bool>> callback) = 0;
6421-
6422     /**
6423      * @brief Gets whether there are stored cookies.
6424      *
6425      * @param callback a callback to be executed when the cookie has checked.
6426      */
6427     virtual void ExistCookies(std::shared_ptr<NWebValueCallback<bool>> callback) = 0;
6428-
6429     /**
6430      * @brief Ensures all cookies currently accessible through the ReturnCookie API are written to
6431      * persistent storage.
6432@@ -88,14 +81,12 @@ public:
6433      * @param callback a callback to be executed when cookies has Stored.
6434      */
6435     virtual void Store(std::shared_ptr<NWebValueCallback<bool>> callback) = 0;
6436-
6437     /**
6438      * @brief Removes all session cookies, which are cookies without an expiration date.
6439      *
6440      * @param callback a callback to be executed when all session cookies has removed.
6441      */
6442     virtual void DeleteSessionCookies(std::shared_ptr<NWebValueCallback<bool>> callback) = 0;
6443-
6444     /**
6445      * @brief Removes all cookies.
6446      *
6447diff --git a/ohos_nweb/include/nweb_geolocation_callback_interface.h b/ohos_nweb/include/nweb_geolocation_callback_interface.h
6448index 4a95f8e8db..5fe586d606 100644
6449--- a/ohos_nweb/include/nweb_geolocation_callback_interface.h
6450+++ b/ohos_nweb/include/nweb_geolocation_callback_interface.h
6451@@ -11,21 +11,21 @@
6452
6453 namespace OHOS::NWeb {
6454 class OHOS_NWEB_EXPORT NWebGeolocationCallbackInterface {
6455- public:
6456-  NWebGeolocationCallbackInterface() = default;
6457+public:
6458+    NWebGeolocationCallbackInterface() = default;
6459
6460-  virtual ~NWebGeolocationCallbackInterface() = default;
6461-  /**
6462-   * @brief Report the geolocation permission status from usrs.
6463-   *
6464-   * @param origin The origin that ask for the geolocation permission.
6465-   * @param allow The geolocation permission status.
6466-   * @param retain Whether to allow the geolocation permission status to be
6467-   * saved to the system.
6468-   */
6469-  virtual void GeolocationCallbackInvoke(const std::string& origin,
6470-                                         bool allow,
6471-                                         bool retain) = 0;
6472+    virtual ~NWebGeolocationCallbackInterface() = default;
6473+    /**
6474+    * @brief Report the geolocation permission status from usrs.
6475+    *
6476+    * @param origin The origin that ask for the geolocation permission.
6477+    * @param allow The geolocation permission status.
6478+    * @param retain Whether to allow the geolocation permission status to be
6479+    * saved to the system.
6480+    */
6481+    virtual void GeolocationCallbackInvoke(const std::string& origin,
6482+                                           bool allow,
6483+                                           bool retain) = 0;
6484 };
6485 }  // namespace OHOS::NWeb
6486
6487diff --git a/ohos_nweb/include/nweb_handler.h b/ohos_nweb/include/nweb_handler.h
6488index af68a9a3d1..ce72bc9580 100644
6489--- a/ohos_nweb/include/nweb_handler.h
6490+++ b/ohos_nweb/include/nweb_handler.h
6491@@ -24,287 +24,283 @@ namespace OHOS::NWeb {
6492  * @brief Describes how pixel bits encoder color data.
6493  */
6494 enum class ImageColorType {
6495-  // Unknown color type.
6496-  COLOR_TYPE_UNKNOWN = -1,
6497+    // Unknown color type.
6498+    COLOR_TYPE_UNKNOWN = -1,
6499
6500-  // RGBA with 8 bits per pixel (32bits total).
6501-  COLOR_TYPE_RGBA_8888 = 0,
6502+    // RGBA with 8 bits per pixel (32bits total).
6503+    COLOR_TYPE_RGBA_8888 = 0,
6504
6505-  // BGRA with 8 bits per pixel (32bits total).
6506-  COLOR_TYPE_BGRA_8888 = 1,
6507+    // BGRA with 8 bits per pixel (32bits total).
6508+    COLOR_TYPE_BGRA_8888 = 1,
6509 };
6510
6511 /**
6512  * @brief Describes how to interpret the alpha value of a pixel.
6513  */
6514 enum class ImageAlphaType {
6515-  // Unknown alpha type.
6516-  ALPHA_TYPE_UNKNOWN = -1,
6517+    // Unknown alpha type.
6518+    ALPHA_TYPE_UNKNOWN = -1,
6519
6520-  // No transparency. The alpha component is ignored.
6521-  ALPHA_TYPE_OPAQUE = 0,
6522+    // No transparency. The alpha component is ignored.
6523+    ALPHA_TYPE_OPAQUE = 0,
6524
6525-  // Transparency with pre-multiplied alpha component.
6526-  ALPHA_TYPE_PREMULTIPLIED = 1,
6527+    // Transparency with pre-multiplied alpha component.
6528+    ALPHA_TYPE_PREMULTIPLIED = 1,
6529
6530-  // Transparency with post-multiplied alpha component.
6531-  ALPHA_TYPE_POSTMULTIPLIED = 2,
6532+    // Transparency with post-multiplied alpha component.
6533+    ALPHA_TYPE_POSTMULTIPLIED = 2,
6534 };
6535
6536 class OHOS_NWEB_EXPORT NWebHandler {
6537- public:
6538-  NWebHandler() = default;
6539-
6540-  virtual ~NWebHandler() = default;
6541-
6542-  virtual void SetNWeb(std::shared_ptr<NWeb> nweb) {}
6543-
6544-  virtual void OnProxyDied() {}
6545-
6546-  virtual void OnRouterPush(const std::string& param) {}
6547-
6548-  virtual void OnMessage(const std::string& param) {}
6549-
6550-  /**
6551-   * @brief Notify the SDK that a web site has finished loading. This method is
6552-   * called only for main frame.
6553-   *
6554-   * @param httpStatusCode The status code for the http request.
6555-   * @param url The url of the web site.
6556-   */
6557-  virtual void OnPageLoadEnd(int httpStatusCode, const std::string& url) {}
6558-
6559-  /**
6560-   * @brief Notify the SDK that a web site has started loading. This method is
6561-   * called once for each main frame load.
6562-   *
6563-   * @param url The url to be loaded.
6564-   */
6565-  virtual void OnPageLoadBegin(const std::string& url) {}
6566-
6567-  /**
6568-   * @brief Report a load error to the SDK.
6569-   *
6570-   * @param errorCode The error code.
6571-   * @param description The error description.
6572-   * @param failingUrl The failed url.
6573-   */
6574-  virtual void OnPageLoadError(int errorCode,
6575-                               const std::string& description,
6576-                               const std::string& failingUrl) {}
6577-
6578-  /**
6579-   * @brief Give the SDK a chance to decide wheather to continue loading the
6580-   * url.
6581-   *
6582-   * @param url The url to be loaded.
6583-   * @return true to cancel the loading, false to continue the loading.
6584-   */
6585-  virtual bool OnHandleInterceptUrlLoading(const std::string& url) {
6586-    return false;
6587-  }
6588-
6589-  /**
6590-   * @brief Notify the SDK that the nweb will load the resource specified by
6591-   * the given url.
6592-   *
6593-   * @param url The url of the resource.
6594-   */
6595-  virtual void OnResource(const std::string& url) {}
6596-
6597-  /**
6598-   * @brief Notify the SDK of the changed document title.
6599-   *
6600-   * @param title The document title.
6601-   */
6602-  virtual void OnPageTitle(const std::string& title) {}
6603-
6604-  /**
6605-   * @brief Notify the SDK the current progress of loading a web site.
6606-   *
6607-   * @param newProgress Loading progress, an integer between 0 and 100.
6608-   */
6609-  virtual void OnLoadingProgress(int newProgress) {}
6610-
6611-  /**
6612-   * @brief Request display and focus for a new nweb.
6613-   *
6614-   */
6615-  virtual void OnFocus() {}
6616-
6617-  /**
6618-   * @brief Obtains a list of all visited history items, used for link coloring
6619-   *
6620-   * @retval visited history
6621-   */
6622-  virtual const std::vector<std::string> VisitedUrlHistory() {
6623-    return std::vector<std::string>();
6624-  }
6625-
6626-  /**
6627-   * @brief Notify the host application of a resource request and allow the
6628-   * application to return the data.
6629-   *
6630-   * @param request the resource response's MIME type, for example {
6631-   * "text/html"}.
6632-   *
6633-   * @retval if NWebUrlResourceResponse is null ,No interception.
6634-   */
6635-  virtual std::shared_ptr<NWebUrlResourceResponse> OnHandleInterceptRequest(
6636-      std::shared_ptr<NWebUrlResourceRequest> request) {
6637-    return nullptr;
6638-  }
6639-
6640-  /**
6641-   * @brief Report web resource loading error to the SDK. These errors usually
6642-   * indicate inability to connect to the server.
6643-   *
6644-   * @param request The request information.
6645-   * @param error The error information.
6646-   */
6647-  virtual void OnResourceLoadError(
6648-      std::shared_ptr<NWebUrlResourceRequest> request,
6649-      std::shared_ptr<NWebUrlResourceError> error) {}
6650-
6651-  /**
6652-   * @brief Notify the SDK that an HTTP error has been received from the server
6653-   * while loading a resource.
6654-   *
6655-   * @param request The request information.
6656-   * @param errorResponse The error occurred.
6657-   */
6658-  virtual void OnHttpError(
6659-      std::shared_ptr<NWebUrlResourceRequest> request,
6660-      std::shared_ptr<NWebUrlResourceResponse> errorResponse) {}
6661-
6662-  /**
6663-   * @brief Notify the SDK of a new favicon for the current web site.
6664-   *
6665-   * @param data The raw image data for the icon.
6666-   * @param width The width of the icon in pixel.
6667-   * @param height The height of the icon in pixel.
6668-   * @param color_type The color data encoding type.
6669-   * @param alpha_type The alpha value of any pixel.
6670-   */
6671-  virtual void OnPageIcon(const void* data,
6672-                          size_t width,
6673-                          size_t height,
6674-                          ImageColorType color_type,
6675-                          ImageAlphaType alpha_type) {}
6676-
6677-  /**
6678-   * @brief Notify the SDK of the url for an touch icon.
6679-   *
6680-   * @param icon_url The icon url.
6681-   * @param precomposed The touch icon type.
6682-   */
6683-  virtual void OnDesktopIconUrl(const std::string& icon_url, bool precomposed) {
6684-  }
6685-
6686-  /**
6687-   * @brief Report a JavaScript console message to the host application.
6688-   *
6689-   * @param message Details of the console message.
6690-   * @return Return true to stop the message from being output to the console.
6691-   */
6692-  virtual bool OnConsoleLog(const NWebConsoleLog& message) { return false; }
6693-
6694-  /**
6695-   * @brief Show prompt to ask for the geolocation permission.
6696-   *
6697-   * @param origin  String: the origin of the resource to get geolocation
6698-   * @param callback  GeolocationCallbackInterface: callback to report
6699-   * geolocation
6700-   */
6701-  virtual void OnGeolocationShow(const std::string& origin,
6702-                                 NWebGeolocationCallbackInterface* callback) {}
6703-
6704-  /**
6705-   * @brief Notify the host application that the web page wants to display a
6706-   * JavaScript alert() dialog.
6707-   *
6708-   * @param url  String: The url of the page requesting the dialog.
6709-   * @param message  String: The message of the dialog.
6710-   * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6711-   * confirm that the user closed the window.
6712-   * @return To show a custom dialog, the app should return true.
6713-   */
6714-  virtual bool OnAlertDialogByJS(const std::string& url,
6715-                                 const std::string& message,
6716-                                 std::shared_ptr<NWebJSDialogResult> result) {
6717-    return false;
6718-  }
6719-
6720-  /**
6721-   * @brief Notify the host application that the web page wants to handle
6722-   * JavaScript onbeforeunload.
6723-   *
6724-   * @param url  String: The url of the page requesting.
6725-   * @param message  String: The message of the dialog.
6726-   * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6727-   * confirm that the user closed the window.
6728-   * @return To show a custom dialog, the app should return true.
6729-   */
6730-  virtual bool OnBeforeUnloadByJS(const std::string& url,
6731-                                  const std::string& message,
6732-                                  std::shared_ptr<NWebJSDialogResult> result) {
6733-    return false;
6734-  }
6735-
6736-  /**
6737-   * @brief Notify the host application that the web page wants to display a
6738-   * JavaScript prompt() dialog.
6739-   *
6740-   * @param url  String: The url of the page requesting the dialog.
6741-   * @param message  String: The message of the dialog.
6742-   * @param defaultValue  String: The default value of the input message.
6743-   * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6744-   * confirm that the user closed the window.
6745-   * @return To show a custom dialog, the app should return true.
6746-   */
6747-  virtual bool OnPromptDialogByJs(const std::string& url,
6748-                                  const std::string& message,
6749-                                  const std::string& defaultValue,
6750-                                  std::shared_ptr<NWebJSDialogResult> result) {
6751-    return false;
6752-  }
6753-
6754-  /**
6755-   * @brief Notify the host application that the web page wants to display a
6756-   * JavaScript Confirm() dialog.
6757-   *
6758-   * @param url  String: The url of the page requesting the dialog.
6759-   * @param message  String: The message of the dialog.
6760-   * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6761-   * confirm that the user closed the window.
6762-   * @return To show a custom dialog, the app should return true.
6763-   */
6764-  virtual bool OnConfirmDialogByJS(const std::string& url,
6765+public:
6766+    NWebHandler() = default;
6767+
6768+    virtual ~NWebHandler() = default;
6769+
6770+    virtual void SetNWeb(std::shared_ptr<NWeb> nweb) {}
6771+
6772+    virtual void OnProxyDied() {}
6773+
6774+    virtual void OnRouterPush(const std::string& param) {}
6775+
6776+    virtual void OnMessage(const std::string& param) {}
6777+
6778+    /**
6779+     * @brief Notify the SDK that a web site has finished loading. This method is
6780+     * called only for main frame.
6781+     *
6782+     * @param httpStatusCode The status code for the http request.
6783+     * @param url The url of the web site.
6784+     */
6785+    virtual void OnPageLoadEnd(int httpStatusCode, const std::string& url) {}
6786+
6787+    /**
6788+     * @brief Notify the SDK that a web site has started loading. This method is
6789+     * called once for each main frame load.
6790+     *
6791+     * @param url The url to be loaded.
6792+     */
6793+    virtual void OnPageLoadBegin(const std::string& url) {}
6794+
6795+    /**
6796+     * @brief Report a load error to the SDK.
6797+     *
6798+     * @param errorCode The error code.
6799+     * @param description The error description.
6800+     * @param failingUrl The failed url.
6801+     */
6802+    virtual void OnPageLoadError(int errorCode,
6803+                                 const std::string& description,
6804+                                 const std::string& failingUrl) {}
6805+
6806+    /**
6807+     * @brief Give the SDK a chance to decide wheather to continue loading the
6808+     * url.
6809+     *
6810+     * @param url The url to be loaded.
6811+     * @return true to cancel the loading, false to continue the loading.
6812+     */
6813+    virtual bool OnHandleInterceptUrlLoading(const std::string& url) {
6814+        return false;
6815+    }
6816+
6817+    /**
6818+     * @brief Notify the SDK that the nweb will load the resource specified by
6819+     * the given url.
6820+     *
6821+     * @param url The url of the resource.
6822+     */
6823+    virtual void OnResource(const std::string& url) {}
6824+
6825+    /**
6826+     * @brief Notify the SDK of the changed document title.
6827+     *
6828+     * @param title The document title.
6829+     */
6830+    virtual void OnPageTitle(const std::string& title) {}
6831+
6832+    /**
6833+     * @brief Notify the SDK the current progress of loading a web site.
6834+     *
6835+     * @param newProgress Loading progress, an integer between 0 and 100.
6836+     */
6837+    virtual void OnLoadingProgress(int newProgress) {}
6838+
6839+    /**
6840+     * @brief Request display and focus for a new nweb.
6841+     *
6842+     */
6843+    virtual void OnFocus() {}
6844+
6845+    /**
6846+     * @brief Obtains a list of all visited history items, used for link coloring
6847+     *
6848+     * @retval visited history
6849+     */
6850+    virtual const std::vector<std::string> VisitedUrlHistory() {
6851+        return std::vector<std::string>();
6852+    }
6853+
6854+    /**
6855+     * @brief Notify the host application of a resource request and allow the
6856+     * application to return the data.
6857+     *
6858+     * @param request the resource response's MIME type, for example {
6859+     * "text/html"}.
6860+     *
6861+     * @retval if NWebUrlResourceResponse is null ,No interception.
6862+     */
6863+    virtual std::shared_ptr<NWebUrlResourceResponse> OnHandleInterceptRequest(
6864+        std::shared_ptr<NWebUrlResourceRequest> request) {
6865+        return nullptr;
6866+    }
6867+
6868+    /**
6869+     * @brief Report web resource loading error to the SDK. These errors usually
6870+     * indicate inability to connect to the server.
6871+     *
6872+     * @param request The request information.
6873+     * @param error The error information.
6874+     */
6875+    virtual void OnResourceLoadError(std::shared_ptr<NWebUrlResourceRequest> request,
6876+                                     std::shared_ptr<NWebUrlResourceError> error) {}
6877+
6878+    /**
6879+     * @brief Notify the SDK that an HTTP error has been received from the server
6880+     * while loading a resource.
6881+     *
6882+     * @param request The request information.
6883+     * @param errorResponse The error occurred.
6884+     */
6885+    virtual void OnHttpError(std::shared_ptr<NWebUrlResourceRequest> request,
6886+                             std::shared_ptr<NWebUrlResourceResponse> errorResponse) {}
6887+
6888+    /**
6889+     * @brief Notify the SDK of a new favicon for the current web site.
6890+     *
6891+     * @param data The raw image data for the icon.
6892+     * @param width The width of the icon in pixel.
6893+     * @param height The height of the icon in pixel.
6894+     * @param color_type The color data encoding type.
6895+     * @param alpha_type The alpha value of any pixel.
6896+     */
6897+    virtual void OnPageIcon(const void* data,
6898+                            size_t width,
6899+                            size_t height,
6900+                            ImageColorType color_type,
6901+                            ImageAlphaType alpha_type) {}
6902+
6903+    /**
6904+     * @brief Notify the SDK of the url for an touch icon.
6905+     *
6906+     * @param icon_url The icon url.
6907+     * @param precomposed The touch icon type.
6908+     */
6909+    virtual void OnDesktopIconUrl(const std::string& icon_url, bool precomposed) {
6910+    }
6911+
6912+    /**
6913+     * @brief Report a JavaScript console message to the host application.
6914+     *
6915+     * @param message Details of the console message.
6916+     * @return Return true to stop the message from being output to the console.
6917+     */
6918+    virtual bool OnConsoleLog(const NWebConsoleLog& message) { return false; }
6919+
6920+    /**
6921+     * @brief Show prompt to ask for the geolocation permission.
6922+     *
6923+     * @param origin  String: the origin of the resource to get geolocation
6924+     * @param callback  GeolocationCallbackInterface: callback to report
6925+     * geolocation
6926+     */
6927+    virtual void OnGeolocationShow(const std::string& origin,
6928+                                   NWebGeolocationCallbackInterface* callback) {}
6929+
6930+    /**
6931+     * @brief Notify the host application that the web page wants to display a
6932+     * JavaScript alert() dialog.
6933+     *
6934+     * @param url  String: The url of the page requesting the dialog.
6935+     * @param message  String: The message of the dialog.
6936+     * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6937+     * confirm that the user closed the window.
6938+     * @return To show a custom dialog, the app should return true.
6939+     */
6940+    virtual bool OnAlertDialogByJS(const std::string& url,
6941                                    const std::string& message,
6942                                    std::shared_ptr<NWebJSDialogResult> result) {
6943-    return false;
6944-  }
6945-
6946-  /**
6947-   * @brief Hide prompt to ask for the geolocation permission.
6948-   */
6949-  virtual void OnGeolocationHide() {}
6950-
6951-  /**
6952-   * @brief
6953-   *
6954-   * @param request  String:
6955-   */
6956-  virtual void OnPermissionRequest(
6957-      std::shared_ptr<NWebAccessRequest> request) {}
6958-
6959-  /**
6960-   * @brief
6961-   *
6962-   * @param request  String:
6963-   */
6964-  virtual void OnPermissionRequestCanceled(
6965-      std::shared_ptr<NWebAccessRequest> request) {}
6966+        return false;
6967+    }
6968+
6969+    /**
6970+     * @brief Notify the host application that the web page wants to handle
6971+     * JavaScript onbeforeunload.
6972+     *
6973+     * @param url  String: The url of the page requesting.
6974+     * @param message  String: The message of the dialog.
6975+     * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6976+     * confirm that the user closed the window.
6977+     * @return To show a custom dialog, the app should return true.
6978+     */
6979+    virtual bool OnBeforeUnloadByJS(const std::string& url,
6980+                                    const std::string& message,
6981+                                    std::shared_ptr<NWebJSDialogResult> result) {
6982+        return false;
6983+    }
6984+
6985+    /**
6986+     * @brief Notify the host application that the web page wants to display a
6987+     * JavaScript prompt() dialog.
6988+     *
6989+     * @param url  String: The url of the page requesting the dialog.
6990+     * @param message  String: The message of the dialog.
6991+     * @param defaultValue  String: The default value of the input message.
6992+     * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
6993+     * confirm that the user closed the window.
6994+     * @return To show a custom dialog, the app should return true.
6995+     */
6996+    virtual bool OnPromptDialogByJs(const std::string& url,
6997+                                    const std::string& message,
6998+                                    const std::string& defaultValue,
6999+                                    std::shared_ptr<NWebJSDialogResult> result) {
7000+        return false;
7001+    }
7002+
7003+    /**
7004+     * @brief Notify the host application that the web page wants to display a
7005+     * JavaScript Confirm() dialog.
7006+     *
7007+     * @param url  String: The url of the page requesting the dialog.
7008+     * @param message  String: The message of the dialog.
7009+     * @param result  std::shared_ptr<NWebJSDialogResult>: A NWebJSDialogResult to
7010+     * confirm that the user closed the window.
7011+     * @return To show a custom dialog, the app should return true.
7012+     */
7013+    virtual bool OnConfirmDialogByJS(const std::string& url,
7014+                                     const std::string& message,
7015+                                     std::shared_ptr<NWebJSDialogResult> result) {
7016+        return false;
7017+    }
7018+
7019+    /**
7020+     * @brief Hide prompt to ask for the geolocation permission.
7021+     */
7022+    virtual void OnGeolocationHide() {}
7023+
7024+    /**
7025+     * @brief
7026+     *
7027+     * @param request  String:
7028+     */
7029+    virtual void OnPermissionRequest(std::shared_ptr<NWebAccessRequest> request) {}
7030+
7031+    /**
7032+     * @brief
7033+     *
7034+     * @param request  String:
7035+     */
7036+    virtual void OnPermissionRequestCanceled(std::shared_ptr<NWebAccessRequest> request) {}
7037 };
7038 }  // namespace OHOS::NWeb
7039
7040diff --git a/ohos_nweb/include/nweb_hit_testresult.h b/ohos_nweb/include/nweb_hit_testresult.h
7041index 4eb0d0915b..510e471280 100755
7042--- a/ohos_nweb/include/nweb_hit_testresult.h
7043+++ b/ohos_nweb/include/nweb_hit_testresult.h
7044@@ -75,7 +75,6 @@ public:
7045 private:
7046     int type_;
7047     std::string extra_;
7048-
7049 };
7050 }
7051
7052diff --git a/ohos_nweb/include/nweb_js_dialog_result.h b/ohos_nweb/include/nweb_js_dialog_result.h
7053index 13b0fe51f0..693a050f4a 100644
7054--- a/ohos_nweb/include/nweb_js_dialog_result.h
7055+++ b/ohos_nweb/include/nweb_js_dialog_result.h
7056@@ -12,19 +12,16 @@ namespace OHOS::NWeb {
7057 class OHOS_NWEB_EXPORT NWebJSDialogResult {
7058 public:
7059     virtual ~NWebJSDialogResult() = default;
7060-
7061     /**
7062      * @brief Handle a confirmation response from the user.
7063      */
7064     virtual void Confirm() = 0;
7065-
7066     /**
7067      * @brief Handle a confirmation response from the user with input message.
7068      *
7069      * @param message confirm message.
7070      */
7071     virtual void Confirm(const std::string &message) = 0;
7072-
7073     /**
7074      * @brief Handle the result if the user cancelled the dialog.
7075      */
7076diff --git a/ohos_nweb/include/nweb_preference.h b/ohos_nweb/include/nweb_preference.h
7077index ca85253000..cd9f3b430a 100644
7078--- a/ohos_nweb/include/nweb_preference.h
7079+++ b/ohos_nweb/include/nweb_preference.h
7080@@ -10,13 +10,11 @@
7081
7082 namespace OHOS::NWeb {
7083 class OHOS_NWEB_EXPORT NWebPreference {
7084-    public:
7085+public:
7086     NWebPreference() = default;
7087     virtual ~NWebPreference() = default;
7088-
7089     enum AccessMode { ALWAYS_ALLOW = 0, NEVER_ALLOW = 1, COMPATIBILITY_MODE = 2 };
7090-
7091-    /* synchronous set web settings and web preferences */
7092+    /* synchronous set NWebPreference and web preferences */
7093     virtual void PutEnableContentAccess(bool flag) = 0;
7094     virtual void PutEnableRawFileAccess(bool flag) = 0;
7095     virtual void PutEnableRawFileAccessFromFileURLs(bool flag) = 0;
7096@@ -46,7 +44,7 @@ class OHOS_NWEB_EXPORT NWebPreference {
7097     AccessMode mode) = 0;
7098     virtual void PutZoomingFunctionEnabled(bool flag) = 0;
7099
7100-    /* get methods*/
7101+    /* get methods */
7102     virtual bool EnableContentAccess() = 0;
7103     virtual bool EnableRawFileAccess() = 0;
7104     virtual bool EnableRawFileAccessFromFileURLs() = 0;
7105diff --git a/ohos_nweb/include/nweb_url_resource_error.h b/ohos_nweb/include/nweb_url_resource_error.h
7106index b24b7fbd90..dafc312994 100644
7107--- a/ohos_nweb/include/nweb_url_resource_error.h
7108+++ b/ohos_nweb/include/nweb_url_resource_error.h
7109@@ -19,7 +19,7 @@ public:
7110      * @brief Gets the error description.
7111      *
7112      * @brief Gets the ErrorInfo.
7113-     *
7114+     *
7115      * @return The description of the error.
7116      */
7117     virtual const std::string &ErrorInfo() const = 0;
7118diff --git a/ohos_nweb/include/nweb_value.h b/ohos_nweb/include/nweb_value.h
7119index ee4c745e3c..e08d162fe9 100644
7120--- a/ohos_nweb/include/nweb_value.h
7121+++ b/ohos_nweb/include/nweb_value.h
7122@@ -16,55 +16,55 @@ namespace OHOS::NWeb {
7123         bool b;
7124     };
7125
7126-    class OHOS_NWEB_EXPORT NWebValue {
7127-    public:
7128-        enum class Type : unsigned char {
7129-            NONE = 0,
7130-            BOOLEAN,
7131-            INTEGER,
7132-            DOUBLE,
7133-            STRING,
7134-            BINARY,
7135-            DICTIONARY,
7136-            LIST
7137-        };
7138+class OHOS_NWEB_EXPORT NWebValue {
7139+public:
7140+    enum class Type : unsigned char {
7141+        NONE = 0,
7142+        BOOLEAN,
7143+        INTEGER,
7144+        DOUBLE,
7145+        STRING,
7146+        BINARY,
7147+        DICTIONARY,
7148+        LIST
7149+    };
7150
7151-        NWebValue(Type type) : type_(type) {}
7152+    NWebValue(Type type) : type_(type) {}
7153
7154-        ~NWebValue() = default;
7155+    ~NWebValue() = default;
7156
7157-        bool GetBoolean() { return data_.b; }
7158+    bool GetBoolean() { return data_.b; }
7159
7160-        void SetBoolean(bool b) { data_.b = b; }
7161+    void SetBoolean(bool b) { data_.b = b; }
7162
7163-        void SetString(std::string str) { str_ = str; }
7164+    void SetString(std::string str) { str_ = str; }
7165
7166-        std::string GetString() { return str_; }
7167+    std::string GetString() { return str_; }
7168
7169-        void SetDouble(double dou) { data_.f = dou; }
7170+    void SetDouble(double dou) { data_.f = dou; }
7171
7172-        double GetDouble() { return data_.f; }
7173+    double GetDouble() { return data_.f; }
7174
7175-        void SetInt(int num) { data_.n = num; }
7176+    void SetInt(int num) { data_.n = num; }
7177
7178-        int GetInt() { return data_.n; }
7179+    int GetInt() { return data_.n; }
7180
7181-        void SetJsonString(std::string json_string) { str_json_ = json_string; }
7182+    void SetJsonString(std::string json_string) { str_json_ = json_string; }
7183
7184-        std::string GetJsonString() { return str_json_; }
7185+    std::string GetJsonString() { return str_json_; }
7186
7187-        Type GetType() { return type_; }
7188+    Type GetType() { return type_; }
7189
7190-        void SetType(Type type) { type_ = type; }
7191+    void SetType(Type type) { type_ = type; }
7192
7193-        int error_ = 0;
7194+    int error_ = 0;
7195
7196-    private:
7197-        Type type_ = Type::NONE;
7198-        data_union data_;
7199-        std::string str_;
7200-        std::string str_json_;
7201-    };
7202+private:
7203+    Type type_ = Type::NONE;
7204+    data_union data_;
7205+    std::string str_;
7206+    std::string str_json_;
7207+};
7208 }
7209
7210 #endif  // NWEB_VALUE_H_
7211diff --git a/ohos_nweb/include/nweb_value_callback.h b/ohos_nweb/include/nweb_value_callback.h
7212index aeba1f792a..4f521b4232 100644
7213--- a/ohos_nweb/include/nweb_value_callback.h
7214+++ b/ohos_nweb/include/nweb_value_callback.h
7215@@ -8,7 +8,7 @@
7216 #include "nweb_export.h"
7217
7218 namespace OHOS::NWeb {
7219-template <typename T>
7220+template<typename T>
7221 class OHOS_NWEB_EXPORT NWebValueCallback {
7222 public:
7223     NWebValueCallback() = default;
7224diff --git a/ohos_nweb/src/cef_delegate/nweb_delegate.cc b/ohos_nweb/src/cef_delegate/nweb_delegate.cc
7225index 16a7c15f74..475195e136 100755
7226--- a/ohos_nweb/src/cef_delegate/nweb_delegate.cc
7227+++ b/ohos_nweb/src/cef_delegate/nweb_delegate.cc
7228@@ -107,6 +107,10 @@ void NWebDelegate::Resize(uint32_t width, uint32_t height) {
7229   if (render_handler_ != nullptr) {
7230     render_handler_->Resize(width, height);
7231   }
7232+  auto browser = GetBrowser();
7233+  if (browser != nullptr && browser->GetHost() != nullptr) {
7234+    browser->GetHost()->WasResized();
7235+  }
7236 }
7237
7238 void NWebDelegate::OnTouchPress(int32_t id, double x, double y) {
7239diff --git a/ohos_nweb/src/cef_delegate/nweb_geolocation_callback.cc b/ohos_nweb/src/cef_delegate/nweb_geolocation_callback.cc
7240index 893b92a9bb..31046871ce 100644
7241--- a/ohos_nweb/src/cef_delegate/nweb_geolocation_callback.cc
7242+++ b/ohos_nweb/src/cef_delegate/nweb_geolocation_callback.cc
7243@@ -13,14 +13,16 @@ void NWebGeolocationCallback::GeolocationCallbackInvoke(
7244     const std::string& origin,
7245     bool allow,
7246     bool retain) {
7247-  if (retain) {
7248-    if (allow) {
7249-      browser_->GetGeolocationPermissions()->Enabled(origin);
7250-    } else {
7251-      browser_->GetGeolocationPermissions()->Disabled(origin);
7252-    }
7253-  }
7254-  browser_->GetPermissionRequestDelegate()->NotifyGeolocationPermission(allow,
7255-                                                                        origin);
7256+  LOG(ERROR) << "NWebGeolocationCallback::GeolocationCallbackInvoke";
7257+  return;
7258+  // if (retain) {
7259+  //   if (allow) {
7260+  //     browser_->GetGeolocationPermissions()->Enabled(origin);
7261+  //   } else {
7262+  //     browser_->GetGeolocationPermissions()->Disabled(origin);
7263+  //   }
7264+  // }
7265+  // browser_->GetPermissionRequestDelegate()->NotifyGeolocationPermission(false,
7266+  //                                                                       origin);
7267 }
7268 }  // namespace OHOS::NWeb
7269\ No newline at end of file
7270diff --git a/ohos_nweb/src/cef_delegate/nweb_handler_delegate.cc b/ohos_nweb/src/cef_delegate/nweb_handler_delegate.cc
7271index 6c3bef39d1..6fc789fd1e 100755
7272--- a/ohos_nweb/src/cef_delegate/nweb_handler_delegate.cc
7273+++ b/ohos_nweb/src/cef_delegate/nweb_handler_delegate.cc
7274@@ -294,7 +294,9 @@ void NWebHandlerDelegate::OnLoadStart(CefRefPtr<CefBrowser> browser,
7275                                       CefRefPtr<CefFrame> frame,
7276                                       TransitionType transition_type) {
7277   LOG(INFO) << "NWebHandlerDelegate::OnLoadStart";
7278-
7279+  if (browser != nullptr && browser->GetHost() != nullptr) {
7280+    browser->GetHost()->SetFocus(true);
7281+  }
7282   if (nweb_handler_ != nullptr) {
7283     nweb_handler_->OnPageLoadBegin(frame->GetURL().ToString());
7284   }
7285diff --git a/ohos_nweb/src/cef_delegate/nweb_render_handler.cc b/ohos_nweb/src/cef_delegate/nweb_render_handler.cc
7286index 4b85ca9122..ae7be00613 100644
7287--- a/ohos_nweb/src/cef_delegate/nweb_render_handler.cc
7288+++ b/ohos_nweb/src/cef_delegate/nweb_render_handler.cc
7289@@ -53,7 +53,21 @@ void NWebRenderHandler::OnPaint(CefRefPtr<CefBrowser> browser,
7290                                 int height) {
7291   // run render callback to take buffer.
7292   // note: buffer must be consumed asap with no lock protected
7293-  if (render_update_cb_ != nullptr) {
7294+  if (render_update_cb_ == nullptr) {
7295+    return;
7296+  }
7297+  if (width != width_ || height != height_) {
7298+    LOG(INFO) << "frame size(" << width << "*" << height
7299+              << ") is not identical to request size (" << width_ << "*"
7300+              << height_ << "), drop this frame";
7301+    constexpr uint8_t kBitsPerPixel = 4;
7302+    uint32_t white_frame_size = width_ * height_ * kBitsPerPixel;
7303+    char* white_frame = new char[white_frame_size];
7304+    const char pixel_in_white = 0xFF;
7305+    (void)memset(white_frame, pixel_in_white, white_frame_size);
7306+    render_update_cb_(white_frame);
7307+    delete[] white_frame;
7308+  } else {
7309     render_update_cb_(reinterpret_cast<const char*>(buffer));
7310   }
7311 }
7312diff --git a/ohos_nweb/src/nweb_execute_process.cc b/ohos_nweb/src/nweb_execute_process.cc
7313new file mode 100644
7314index 0000000000..02e9ea1950
7315--- /dev/null
7316+++ b/ohos_nweb/src/nweb_execute_process.cc
7317@@ -0,0 +1,35 @@
7318+// Copyright (c) 2022 Huawei Device Co., Ltd. All rights reserved.
7319+// Use of this source code is governed by a BSD-style license that can be
7320+// found in the LICENSE file.
7321+
7322+#include <unistd.h>
7323+#include <sstream>
7324+
7325+#include "include/cef_app.h"
7326+#include "nweb_export.h"
7327+#include "nweb_hilog.h"
7328+
7329+extern "C" OHOS_NWEB_EXPORT void NWebRenderMain(const char* args) {
7330+  WVLOG_I("NWebRenderMain start, pid=%{public}d", getpid());
7331+
7332+  std::string args_str = args;
7333+  std::stringstream args_ss(args_str);
7334+  const char separator = '#';
7335+  std::vector<std::string> argv_str;
7336+  std::string arg_str;
7337+  while(std::getline(args_ss, arg_str, separator)) {
7338+    argv_str.push_back(arg_str);
7339+  }
7340+
7341+  std::vector<char*> argv_cstr;
7342+  int argc = argv_str.size();
7343+  argv_cstr.reserve(argc + 1);
7344+  for (const auto& arg : argv_str)
7345+    argv_cstr.push_back(const_cast<char*>(arg.c_str()));
7346+  argv_cstr.push_back(nullptr);
7347+
7348+  CefMainArgs main_args(argc, const_cast<char**>(argv_cstr.data()));
7349+  (void)CefExecuteProcess(main_args, NULL, NULL);
7350+
7351+  WVLOG_I("NWebRenderMain end, pid=%{public}d", getpid());
7352+}
7353\ No newline at end of file
7354diff --git a/ohos_nweb/src/nweb_impl.cc b/ohos_nweb/src/nweb_impl.cc
7355index 925a5561ef..21eeab89f2 100755
7356--- a/ohos_nweb/src/nweb_impl.cc
7357+++ b/ohos_nweb/src/nweb_impl.cc
7358@@ -135,9 +135,11 @@ bool NWebImpl::InitWebEngine() {
7359 void NWebImpl::InitWebEngineArgs(const NWebInitArgs& init_args) {
7360   web_engine_args_.clear();
7361   web_engine_args_.emplace_back("/system/bin/web_render");
7362+  // web_engine_args_.emplace_back("--disable-gpu");
7363   web_engine_args_.emplace_back("--in-process-gpu");
7364   web_engine_args_.emplace_back("--disable-dev-shm-usage");
7365   web_engine_args_.emplace_back("--no-unsandboxed-zygote");
7366+  web_engine_args_.emplace_back("--no-zygote");
7367   web_engine_args_.emplace_back("--off-screen-frame-rate=60");
7368   web_engine_args_.emplace_back("--enable-features=UseOzonePlatform");
7369   web_engine_args_.emplace_back("-ozone-platform=headless");
7370@@ -335,7 +337,7 @@ std::string NWebImpl::Title() {
7371   return nweb_delegate_->Title();
7372 }
7373
7374-const HitTestResult NWebImpl::GetHitTestResult() const {
7375+HitTestResult NWebImpl::GetHitTestResult() const {
7376   return nweb_delegate_->GetHitTestResult();
7377 }
7378
7379diff --git a/ohos_nweb/src/nweb_impl.h b/ohos_nweb/src/nweb_impl.h
7380index 559f8487f2..dd0c16f178 100755
7381--- a/ohos_nweb/src/nweb_impl.h
7382+++ b/ohos_nweb/src/nweb_impl.h
7383@@ -56,7 +56,7 @@ class NWebImpl : public NWeb {
7384   void SetNWebHandler(std::shared_ptr<NWebHandler> handler) override;
7385   const std::shared_ptr<NWebHandler> GetNWebHandler() const override;
7386   std::string Title() override;
7387-  const HitTestResult GetHitTestResult() const override;
7388+  HitTestResult GetHitTestResult() const override;
7389   int PageLoadProgress() override;
7390   int ContentHeight() override;
7391   float Scale() override;
7392diff --git a/ohos_nweb/src/nweb_input_handler.cc b/ohos_nweb/src/nweb_input_handler.cc
7393index 710cbc5df4..78ea32c2b0 100644
7394--- a/ohos_nweb/src/nweb_input_handler.cc
7395+++ b/ohos_nweb/src/nweb_input_handler.cc
7396@@ -60,16 +60,6 @@ void NWebInputHandler::OnTouchMove(int32_t id, double x, double y) {
7397     return;
7398   }
7399
7400-  // For multi-finger touch-move event get from ArkUI, some fingers may start
7401-  // move without previous touch-press event, which may cause these fingers
7402-  // unrecognized by web_engine, and multi-finger gestures like pinch unsupport.
7403-  // For this reason, the first touch-move event would be treated as touch-press
7404-  // event.
7405-  if (touch_press_id_map_.find(id) == touch_press_id_map_.end() ||
7406-      !touch_press_id_map_.at(id)) {
7407-    this->OnTouchPress(id, x, y);
7408-  }
7409-
7410   nweb_delegate_->OnTouchMove(id, x, y);
7411   last_x_ = x;
7412   last_y_ = y;
7413diff --git a/ohos_nweb/src/nweb_inputmethod_handler.cc b/ohos_nweb/src/nweb_inputmethod_handler.cc
7414index 0456edc290..5bb55cf39c 100644
7415--- a/ohos_nweb/src/nweb_inputmethod_handler.cc
7416+++ b/ohos_nweb/src/nweb_inputmethod_handler.cc
7417@@ -41,7 +41,12 @@ class OnTextChangedListenerImpl
7418   }
7419
7420   void SendKeyboardInfo(const OHOS::MiscServices::KeyboardInfo& info) override {
7421-
7422+    auto status = info.GetKeyboardStatus();
7423+    if (status == OHOS::MiscServices::KeyboardStatus::SHOW) {
7424+      handler_->SetIMEStatus(true);
7425+    } else if (status == OHOS::MiscServices::KeyboardStatus::HIDE) {
7426+      handler_->SetIMEStatus(false);
7427+    }
7428   }
7429
7430   void SetKeyboardStatus(bool status) override {
7431@@ -76,11 +81,14 @@ class InputMethodTask : public CefTask {
7432 };
7433
7434 NWebInputMethodHandler::NWebInputMethodHandler()
7435-    : selected_from_(0), selected_to_(0) {}
7436+    : selected_from_(0), selected_to_(0) {
7437+  g_listener = nullptr;
7438+}
7439
7440 NWebInputMethodHandler::~NWebInputMethodHandler() {}
7441
7442 void NWebInputMethodHandler::Attach(CefRefPtr<CefBrowser> browser) {
7443+  composing_text_.clear();
7444   browser_ = browser;
7445   if (ime_shown_) {
7446     return;
7447@@ -105,6 +113,11 @@ void NWebInputMethodHandler::OnTextSelectionChanged(
7448     CefRefPtr<CefBrowser> browser,
7449     const CefString& selected_text,
7450     const CefRange& selected_range) {
7451+  if (ime_text_composing_ && !composing_text_.empty()) {
7452+    if (browser_ != nullptr && browser_->GetHost() != nullptr) {
7453+      browser_->GetHost()->ImeFinishComposingText(false);
7454+    }
7455+  }
7456   selected_text_ = selected_text.ToString16();
7457   selected_from_ = selected_range.from;
7458   selected_to_ = selected_range.to;
7459@@ -148,6 +161,7 @@ void NWebInputMethodHandler::SetIMEStatusOnUI(bool status) {
7460   if (!status && ime_text_composing_) {
7461     browser_->GetHost()->ImeFinishComposingText(false);
7462     ime_text_composing_ = false;
7463+    composing_text_.clear();
7464   }
7465   ime_shown_ = status;
7466 }
7467diff --git a/ohos_nweb/src/nweb_render_main.cc b/ohos_nweb/src/nweb_render_main.cc
7468new file mode 100644
7469index 0000000000..b0b3122e56
7470--- /dev/null
7471+++ b/ohos_nweb/src/nweb_render_main.cc
7472@@ -0,0 +1,34 @@
7473+// Copyright (c) 2022 Huawei Device Co., Ltd. All rights reserved.
7474+// Use of this source code is governed by a BSD-style license that can be
7475+// found in the LICENSE file.
7476+
7477+#include <unistd.h>
7478+#include <sstream>
7479+
7480+#include "include/cef_app.h"
7481+#include "nweb_export.h"
7482+#include "nweb_hilog.h"
7483+
7484+extern "C" OHOS_NWEB_EXPORT void NWebRenderMain(const char* args) {
7485+  WVLOG_I("NWebRenderMain start, pid=%{public}d", getpid());
7486+
7487+  std::string args_str = args;
7488+  std::stringstream args_ss(args_str);
7489+  const char separator = '#';
7490+  std::vector<std::string> argv_str;
7491+  std::string arg_str;
7492+  while(std::getline(args_ss, arg_str, separator)) {
7493+    argv_str.push_back(arg_str);
7494+  }
7495+  std::vector<char*> argv_cstr;
7496+  int argc = argv_str.size();
7497+  argv_cstr.reserve(argc + 1);
7498+  for (const auto& arg : argv_str)
7499+    argv_cstr.push_back(const_cast<char*>(arg.c_str()));
7500+  argv_cstr.push_back(nullptr);
7501+
7502+  CefMainArgs main_args(argc, const_cast<char**>(argv_cstr.data()));
7503+  (void)CefExecuteProcess(main_args, NULL, NULL);
7504+
7505+  WVLOG_I("NWebRenderMain end, pid=%{public}d", getpid());
7506+}
7507\ No newline at end of file
7508diff --git a/ohos_nweb/src/ohos_nweb_main.cc b/ohos_nweb/src/ohos_nweb_main.cc
7509index defaae1499..bcce6266f6 100644
7510--- a/ohos_nweb/src/ohos_nweb_main.cc
7511+++ b/ohos_nweb/src/ohos_nweb_main.cc
7512@@ -3,15 +3,67 @@
7513 // found in the LICENSE file.
7514
7515 #include <unistd.h>
7516+#include <dlfcn.h>
7517 #include "include/cef_app.h"
7518 #include "nweb_hilog.h"
7519
7520 int main(int argc, const char* argv[]) {
7521   WVLOG_I("nweb subprocess %{public}s begin, pid=%{public}d", argv[0],
7522           getpid());
7523-
7524-  CefMainArgs main_args(argc, const_cast<char**>(argv));
7525-  (void)CefExecuteProcess(main_args, NULL, NULL);
7526+#ifdef __MUSL__
7527+  Dl_namespace dlns;
7528+  dlns_init(&dlns, "nweb_test_ns");
7529+  dlns_create(&dlns, "/data/app/el1/bundle/public/com.ohos.nweb/libs/arm");
7530+  const std::string LIB_PATH_NWEB_RENDER = "libnweb_render.so";
7531+  const std::string LIB_PATH_WEB_ENGINE = "libweb_engine.so";
7532+  void *libHandleWebEngine = dlopen_ns(&dlns, LIB_PATH_WEB_ENGINE.c_str(), RTLD_NOW);
7533+  if (libHandleWebEngine == nullptr) {
7534+      WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", LIB_PATH_WEB_ENGINE.c_str(), dlerror());
7535+      return -1;
7536+  }
7537+  void *libHandleNWebRender = dlopen_ns(&dlns, LIB_PATH_NWEB_RENDER.c_str(), RTLD_NOW);
7538+  if (libHandleNWebRender == nullptr) {
7539+      WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", LIB_PATH_NWEB_RENDER.c_str(), dlerror());
7540+      return -1;
7541+  }
7542+#else
7543+  const std::string LOAD_LIB_DIR_INSTALLATION = "/data/app/el1/bundle/public/com.ohos.nweb/libs/arm";
7544+  const std::string LIB_PATH_WEB_ENGINE = LOAD_LIB_DIR_INSTALLATION + "/libweb_engine.so";
7545+  const std::string LIB_PATH_NWEB_RENDER = LOAD_LIB_DIR_INSTALLATION + "/libnweb_render.so";
7546+  void *libHandleWebEngine = ::dlopen(LIB_PATH_WEB_ENGINE.c_str(), RTLD_NOW);
7547+  if (libHandleWebEngine == nullptr) {
7548+    WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", LIB_PATH_WEB_ENGINE.c_str(), dlerror());
7549+    return -1;
7550+  }
7551+  void *libHandleNWebRender = ::dlopen(LIB_PATH_NWEB_RENDER.c_str(), RTLD_NOW);
7552+  if (libHandleNWebRender == nullptr) {
7553+    WVLOG_E("fail to dlopen %{public}s, errmsg=%{public}s", LIB_PATH_NWEB_RENDER.c_str(), dlerror());
7554+    return -1;
7555+  }
7556+#endif
7557+  using NWebRenderMainFunc = void (*)(const char* args);
7558+  const std::string NWEB_RENDER_MAIN = "NWebRenderMain";
7559+  NWebRenderMainFunc func =
7560+        reinterpret_cast<NWebRenderMainFunc>(dlsym(libHandleNWebRender, NWEB_RENDER_MAIN.c_str()));
7561+  if (func == nullptr) {
7562+    WVLOG_E("fail to dlsym %{public}s from libnweb_render.so", NWEB_RENDER_MAIN.c_str());
7563+    return -1;
7564+  }
7565+  std::stringstream argv_ss;
7566+  const char separator = '#';
7567+  for (int i=0; i<argc-1; ++i) {
7568+    argv_ss << argv[i] << separator;
7569+  }
7570+  argv_ss << argv[argc-1];
7571+  func(argv_ss.str().data());
7572+  if (libHandleWebEngine != nullptr) {
7573+    ::dlclose(libHandleWebEngine);
7574+    libHandleWebEngine = nullptr;
7575+  }
7576+  if (libHandleNWebRender != nullptr) {
7577+    ::dlclose(libHandleNWebRender);
7578+    libHandleNWebRender = nullptr;
7579+  }
7580
7581   WVLOG_I("nweb subprocess %{public}s end, pid=%{public}d", argv[0],
7582           getpid());
7583diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h
7584index 9dfebfcc17..d4ab27f084 100644
7585--- a/sandbox/win/src/sandbox.h
7586+++ b/sandbox/win/src/sandbox.h
7587@@ -140,7 +140,7 @@ class BrokerServices {
7588 //   }
7589 //
7590 // For more information see the BrokerServices API documentation.
7591-class TargetServices {
7592+class [[clang::lto_visibility_public]] TargetServices {
7593  public:
7594   // Initializes the target. Must call this function before any other.
7595   // returns ALL_OK if successful. All other return values imply failure.
7596diff --git a/services/device/geolocation/BUILD.gn b/services/device/geolocation/BUILD.gn
7597index 27c8bcf097..8bc76eac2b 100644
7598--- a/services/device/geolocation/BUILD.gn
7599+++ b/services/device/geolocation/BUILD.gn
7600@@ -64,20 +64,20 @@ source_set("geolocation") {
7601     "//services/network/public/cpp",
7602   ]
7603
7604-  if (is_ohos) {
7605-    sources += [
7606-      "ohos/location_provider_ohos.cc",
7607-      "ohos/location_provider_ohos.h",
7608-    ]
7609-    import("//build/config/ohos/config.gni")
7610-    include_dirs = ohos_src_includes
7611-    lib_dirs = ohos_libs_dir
7612-    libs = [
7613-      "locator_sdk.z",
7614-      "ipc_core.z",
7615-      "lbsservice_common.z",
7616-    ]
7617-  }
7618+#if (is_ohos) {
7619+#  sources += [
7620+#    "ohos/location_provider_ohos.cc",
7621+#    "ohos/location_provider_ohos.h",
7622+#  ]
7623+#  import("//build/config/ohos/config.gni")
7624+#  include_dirs = ohos_src_includes
7625+#  lib_dirs = ohos_libs_dir
7626+#  libs = [
7627+#    "locator_sdk.z",
7628+#    "ipc_core.z",
7629+#    "lbsservice_common.z",
7630+#  ]
7631+#}
7632
7633   if (is_android) {
7634     sources += [
7635diff --git a/services/device/geolocation/location_arbitrator.cc b/services/device/geolocation/location_arbitrator.cc
7636index 3932492409..a36fdcaf39 100644
7637--- a/services/device/geolocation/location_arbitrator.cc
7638+++ b/services/device/geolocation/location_arbitrator.cc
7639@@ -163,7 +163,7 @@ LocationArbitrator::NewNetworkLocationProvider(
7640
7641 std::unique_ptr<LocationProvider>
7642 LocationArbitrator::NewSystemLocationProvider() {
7643-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
7644+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA) || defined(OS_OHOS)
7645   return nullptr;
7646 #else
7647   return device::NewSystemLocationProvider();
7648diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
7649index 374ea34a12..c2a4e52a90 100644
7650--- a/services/network/cors/cors_url_loader.cc
7651+++ b/services/network/cors/cors_url_loader.cc
7652@@ -296,13 +296,6 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
7653   DCHECK(forwarding_client_);
7654   DCHECK(!deferred_redirect_url_);
7655
7656-  if (request_.redirect_mode == mojom::RedirectMode::kManual) {
7657-    deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
7658-    forwarding_client_->OnReceiveRedirect(redirect_info,
7659-                                          std::move(response_head));
7660-    return;
7661-  }
7662-
7663   // If |CORS flag| is set and a CORS check for |request| and |response| returns
7664   // failure, then return a network error.
7665   if (fetch_cors_flag_ && IsCorsEnabledRequestMode(request_.mode)) {
7666@@ -320,6 +313,13 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
7667     }
7668   }
7669
7670+  if (request_.redirect_mode == mojom::RedirectMode::kManual) {
7671+    deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
7672+    forwarding_client_->OnReceiveRedirect(redirect_info,
7673+                                          std::move(response_head));
7674+    return;
7675+  }
7676+
7677   timing_allow_failed_flag_ = !PassesTimingAllowOriginCheck(*response_head);
7678
7679   // Because we initiate a new request on redirect in some cases, we cannot
7680diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
7681index 77cd931b5f..c16affe394 100644
7682--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
7683+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
7684@@ -105,7 +105,8 @@ void CoordinatorImpl::RegisterClientProcess(
7685     const base::Optional<std::string>& service_name) {
7686   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
7687   mojo::Remote<mojom::ClientProcess> process(std::move(client_process));
7688-  coordinator_receivers_.Add(this, std::move(receiver), process_id);
7689+  if (receiver.is_valid())
7690+    coordinator_receivers_.Add(this, std::move(receiver), process_id);
7691   process.set_disconnect_handler(
7692       base::BindOnce(&CoordinatorImpl::UnregisterClientProcess,
7693                      base::Unretained(this), process_id));
7694diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
7695index ca0e8d8441..ae9ef93eaf 100644
7696--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
7697+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
7698@@ -24,6 +24,11 @@ void ClientProcessImpl::CreateInstance(
7699     mojo::PendingReceiver<mojom::ClientProcess> receiver,
7700     mojo::PendingRemote<mojom::Coordinator> coordinator,
7701     bool is_browser_process) {
7702+  // Intentionally disallow non-browser processes from ever holding a
7703+  // Coordinator.
7704+  if (!is_browser_process)
7705+    coordinator.reset();
7706+
7707   static ClientProcessImpl* instance = nullptr;
7708   if (!instance) {
7709     instance = new ClientProcessImpl(
7710@@ -39,10 +44,12 @@ ClientProcessImpl::ClientProcessImpl(
7711     mojo::PendingRemote<mojom::Coordinator> coordinator,
7712     bool is_browser_process,
7713     bool initialize_memory_instrumentation)
7714-    : receiver_(this, std::move(receiver)) {
7715+    : receiver_(this, std::move(receiver)),
7716+      is_browser_process_(is_browser_process) {
7717   if (initialize_memory_instrumentation) {
7718     // Initialize the public-facing MemoryInstrumentation helper.
7719-    MemoryInstrumentation::CreateInstance(std::move(coordinator));
7720+    MemoryInstrumentation::CreateInstance(std::move(coordinator),
7721+                                          is_browser_process);
7722   } else {
7723     coordinator_.Bind(std::move(coordinator));
7724   }
7725@@ -109,6 +116,8 @@ void ClientProcessImpl::OnChromeMemoryDumpDone(
7726 void ClientProcessImpl::RequestGlobalMemoryDump_NoCallback(
7727     base::trace_event::MemoryDumpType dump_type,
7728     base::trace_event::MemoryDumpLevelOfDetail level_of_detail) {
7729+  CHECK(is_browser_process_);
7730+
7731   if (!task_runner_->RunsTasksInCurrentSequence()) {
7732     task_runner_->PostTask(
7733         FROM_HERE,
7734diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
7735index 6dd8c55823..8c2c20c449 100644
7736--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
7737+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
7738@@ -96,6 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
7739   mojo::Remote<mojom::Coordinator> coordinator_;
7740   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
7741
7742+  // Only browser process is allowed to request memory dumps.
7743+  const bool is_browser_process_;
7744+
7745   // TODO(crbug.com/728199): The observer is only used to setup and tear down
7746   // MemoryDumpManager in each process. Setting up MemoryDumpManager should
7747   // be moved away from TracingObserver.
7748diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
7749index c81d5f83bf..ec90ab9211 100644
7750--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
7751+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
7752@@ -21,10 +21,11 @@ void WrapGlobalMemoryDump(
7753
7754 // static
7755 void MemoryInstrumentation::CreateInstance(
7756-    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
7757-        coordinator) {
7758+    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
7759+    bool is_browser_process) {
7760   DCHECK(!g_instance);
7761-  g_instance = new MemoryInstrumentation(std::move(coordinator));
7762+  g_instance =
7763+      new MemoryInstrumentation(std::move(coordinator), is_browser_process);
7764 }
7765
7766 // static
7767@@ -33,8 +34,10 @@ MemoryInstrumentation* MemoryInstrumentation::GetInstance() {
7768 }
7769
7770 MemoryInstrumentation::MemoryInstrumentation(
7771-    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator)
7772-    : coordinator_(std::move(coordinator)) {}
7773+    mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
7774+    bool is_browser_process)
7775+    : coordinator_(std::move(coordinator)),
7776+      is_browser_process_(is_browser_process) {}
7777
7778 MemoryInstrumentation::~MemoryInstrumentation() {
7779   g_instance = nullptr;
7780@@ -43,6 +46,7 @@ MemoryInstrumentation::~MemoryInstrumentation() {
7781 void MemoryInstrumentation::RequestGlobalDump(
7782     const std::vector<std::string>& allocator_dump_names,
7783     RequestGlobalDumpCallback callback) {
7784+  CHECK(is_browser_process_);
7785   coordinator_->RequestGlobalMemoryDump(
7786       MemoryDumpType::SUMMARY_ONLY, MemoryDumpLevelOfDetail::BACKGROUND,
7787       MemoryDumpDeterminism::NONE, allocator_dump_names,
7788@@ -52,6 +56,7 @@ void MemoryInstrumentation::RequestGlobalDump(
7789 void MemoryInstrumentation::RequestPrivateMemoryFootprint(
7790     base::ProcessId pid,
7791     RequestGlobalDumpCallback callback) {
7792+  CHECK(is_browser_process_);
7793   coordinator_->RequestPrivateMemoryFootprint(
7794       pid, base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
7795 }
7796@@ -60,6 +65,7 @@ void MemoryInstrumentation::RequestGlobalDumpForPid(
7797     base::ProcessId pid,
7798     const std::vector<std::string>& allocator_dump_names,
7799     RequestGlobalDumpCallback callback) {
7800+  CHECK(is_browser_process_);
7801   coordinator_->RequestGlobalMemoryDumpForPid(
7802       pid, allocator_dump_names,
7803       base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
7804@@ -70,6 +76,7 @@ void MemoryInstrumentation::RequestGlobalDumpAndAppendToTrace(
7805     MemoryDumpLevelOfDetail level_of_detail,
7806     MemoryDumpDeterminism determinism,
7807     RequestGlobalMemoryDumpAndAppendToTraceCallback callback) {
7808+  CHECK(is_browser_process_);
7809   coordinator_->RequestGlobalMemoryDumpAndAppendToTrace(
7810       dump_type, level_of_detail, determinism, std::move(callback));
7811 }
7812diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
7813index 3264917890..72157b5345 100644
7814--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
7815+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
7816@@ -34,7 +34,8 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
7817
7818   static void CreateInstance(
7819       mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
7820-          coordinator);
7821+          coordinator,
7822+      bool is_browser_process);
7823   static MemoryInstrumentation* GetInstance();
7824
7825   // Retrieves a Coordinator interface to communicate with the service. This is
7826@@ -100,12 +101,16 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
7827  private:
7828   explicit MemoryInstrumentation(
7829       mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
7830-          coordinator);
7831+          coordinator,
7832+      bool is_browser_process);
7833   ~MemoryInstrumentation();
7834
7835   const mojo::SharedRemote<memory_instrumentation::mojom::Coordinator>
7836       coordinator_;
7837
7838+  // Only browser process is allowed to request memory dumps.
7839+  const bool is_browser_process_;
7840+
7841   DISALLOW_COPY_AND_ASSIGN(MemoryInstrumentation);
7842 };
7843
7844diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
7845index 2a37d497b4..7b4ee07dbb 100644
7846--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
7847+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
7848@@ -477,9 +477,13 @@ const gpu::GpuFeatureInfo& ContextProviderCommandBuffer::GetGpuFeatureInfo()
7849 void ContextProviderCommandBuffer::OnLostContext() {
7850   CheckValidThreadOrLockAcquired();
7851
7852-  // Ensure |this| isn't destroyed in the middle of OnLostContext() if observers
7853-  // drop all references to it.
7854-  scoped_refptr<ContextProviderCommandBuffer> ref(this);
7855+  // Observers may drop the last persistent references to `this`, but there may
7856+  // be weak references in use further up the stack. This task is posted to
7857+  // ensure that destruction is deferred until it's safe.
7858+  base::SequencedTaskRunnerHandle::Get()->PostTask(
7859+      FROM_HERE,
7860+      base::BindOnce([](scoped_refptr<ContextProviderCommandBuffer>) {},
7861+                     base::WrapRefCounted(this)));
7862
7863   for (auto& observer : observers_)
7864     observer.OnContextLost();
7865diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
7866index 34e736e80d..2479803044 100644
7867--- a/storage/browser/blob/blob_registry_impl.cc
7868+++ b/storage/browser/blob/blob_registry_impl.cc
7869@@ -629,13 +629,14 @@ void BlobRegistryImpl::GetBlobFromUUID(
7870 void BlobRegistryImpl::URLStoreForOrigin(
7871     const url::Origin& origin,
7872     mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver) {
7873-  // TODO(mek): Pass origin on to BlobURLStoreImpl so it can use it to generate
7874-  // Blob URLs, and verify at this point that the renderer can create URLs for
7875-  // that origin.
7876   Delegate* delegate = receivers_.current_context().get();
7877   DCHECK(delegate);
7878+  if (!origin.opaque() && !delegate->CanCommitURL(origin.GetURL())) {
7879+    mojo::ReportBadMessage(
7880+        "Non committable origin passed to BlobRegistryImpl::URLStoreForOrigin");
7881+  }
7882   auto self_owned_associated_receiver = mojo::MakeSelfOwnedAssociatedReceiver(
7883-      std::make_unique<BlobURLStoreImpl>(url_registry_, delegate),
7884+      std::make_unique<BlobURLStoreImpl>(origin, url_registry_),
7885       std::move(receiver));
7886   if (g_url_store_creation_hook)
7887     g_url_store_creation_hook->Run(self_owned_associated_receiver);
7888diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
7889index b46ee60849..02281e3e5f 100644
7890--- a/storage/browser/blob/blob_url_store_impl.cc
7891+++ b/storage/browser/blob/blob_url_store_impl.cc
7892@@ -5,6 +5,7 @@
7893 #include "storage/browser/blob/blob_url_store_impl.h"
7894
7895 #include "base/bind.h"
7896+#include "base/strings/strcat.h"
7897 #include "mojo/public/cpp/bindings/receiver_set.h"
7898 #include "storage/browser/blob/blob_impl.h"
7899 #include "storage/browser/blob/blob_url_loader_factory.h"
7900@@ -58,9 +59,9 @@ class BlobURLTokenImpl : public blink::mojom::BlobURLToken {
7901   const base::UnguessableToken token_;
7902 };
7903
7904-BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
7905-                                   BlobRegistryImpl::Delegate* delegate)
7906-    : registry_(std::move(registry)), delegate_(delegate) {}
7907+BlobURLStoreImpl::BlobURLStoreImpl(const url::Origin& origin,
7908+                                   base::WeakPtr<BlobUrlRegistry> registry)
7909+    : origin_(origin), registry_(std::move(registry)) {}
7910
7911 BlobURLStoreImpl::~BlobURLStoreImpl() {
7912   if (registry_) {
7913@@ -72,20 +73,9 @@ BlobURLStoreImpl::~BlobURLStoreImpl() {
7914 void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
7915                                 const GURL& url,
7916                                 RegisterCallback callback) {
7917-  if (!url.SchemeIsBlob()) {
7918-    mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register");
7919-    std::move(callback).Run();
7920-    return;
7921-  }
7922-  if (!delegate_->CanCommitURL(url)) {
7923-    mojo::ReportBadMessage(
7924-        "Non committable URL passed to BlobURLStore::Register");
7925-    std::move(callback).Run();
7926-    return;
7927-  }
7928-  if (BlobUrlUtils::UrlHasFragment(url)) {
7929-    mojo::ReportBadMessage(
7930-        "URL with fragment passed to BlobURLStore::Register");
7931+  // TODO(mek): Generate blob URLs here, rather than validating the URLs the
7932+  // renderer process generated.
7933+  if (!BlobUrlIsValid(url, "Register")) {
7934     std::move(callback).Run();
7935     return;
7936   }
7937@@ -97,19 +87,8 @@ void BlobURLStoreImpl::Register(mojo::PendingRemote<blink::mojom::Blob> blob,
7938 }
7939
7940 void BlobURLStoreImpl::Revoke(const GURL& url) {
7941-  if (!url.SchemeIsBlob()) {
7942-    mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Revoke");
7943-    return;
7944-  }
7945-  if (!delegate_->CanCommitURL(url)) {
7946-    mojo::ReportBadMessage(
7947-        "Non committable URL passed to BlobURLStore::Revoke");
7948+  if (!BlobUrlIsValid(url, "Revoke"))
7949     return;
7950-  }
7951-  if (BlobUrlUtils::UrlHasFragment(url)) {
7952-    mojo::ReportBadMessage("URL with fragment passed to BlobURLStore::Revoke");
7953-    return;
7954-  }
7955
7956   if (registry_)
7957     registry_->RemoveUrlMapping(url);
7958@@ -125,6 +104,40 @@ void BlobURLStoreImpl::Resolve(const GURL& url, ResolveCallback callback) {
7959   std::move(callback).Run(std::move(blob));
7960 }
7961
7962+bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
7963+                                      const char* method) const {
7964+  if (!url.SchemeIsBlob()) {
7965+    mojo::ReportBadMessage(
7966+        base::StrCat({"Invalid scheme passed to BlobURLStore::", method}));
7967+    return false;
7968+  }
7969+  url::Origin url_origin = url::Origin::Create(url);
7970+  // For file:// origins blink sometimes creates blob URLs with "null" as origin
7971+  // and other times "file://" (based on a runtime setting). On the other hand,
7972+  // `origin_` will always be a non-opaque file: origin for pages loaded from
7973+  // file:// URLs. To deal with this, we treat file:// origins and
7974+  // opaque origins separately from non-opaque origins.
7975+  bool valid_origin = true;
7976+  if (url_origin.scheme() == url::kFileScheme) {
7977+    valid_origin = origin_.scheme() == url::kFileScheme;
7978+  } else if (url_origin.opaque()) {
7979+    valid_origin = origin_.opaque() || origin_.scheme() == url::kFileScheme;
7980+  } else {
7981+    valid_origin = origin_ == url_origin;
7982+  }
7983+  if (!valid_origin) {
7984+    mojo::ReportBadMessage(base::StrCat(
7985+        {"URL with invalid origin passed to BlobURLStore::", method}));
7986+    return false;
7987+  }
7988+  if (BlobUrlUtils::UrlHasFragment(url)) {
7989+    mojo::ReportBadMessage(
7990+        base::StrCat({"URL with fragment passed to BlobURLStore::", method}));
7991+    return false;
7992+  }
7993+  return true;
7994+}
7995+
7996 void BlobURLStoreImpl::ResolveAsURLLoaderFactory(
7997     const GURL& url,
7998     mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
7999diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h
8000index 6b4a738a46..3cada75583 100644
8001--- a/storage/browser/blob/blob_url_store_impl.h
8002+++ b/storage/browser/blob/blob_url_store_impl.h
8003@@ -11,8 +11,9 @@
8004 #include "mojo/public/cpp/bindings/pending_receiver.h"
8005 #include "mojo/public/cpp/bindings/pending_remote.h"
8006 #include "mojo/public/cpp/bindings/remote.h"
8007-#include "storage/browser/blob/blob_registry_impl.h"
8008+#include "storage/browser/blob/blob_url_registry.h"
8009 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
8010+#include "url/origin.h"
8011
8012 namespace storage {
8013
8014@@ -21,8 +22,8 @@ class BlobUrlRegistry;
8015 class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
8016     : public blink::mojom::BlobURLStore {
8017  public:
8018-  BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
8019-                   BlobRegistryImpl::Delegate* delegate);
8020+  BlobURLStoreImpl(const url::Origin& origin,
8021+                   base::WeakPtr<BlobUrlRegistry> registry);
8022   ~BlobURLStoreImpl() override;
8023
8024   void Register(mojo::PendingRemote<blink::mojom::Blob> blob,
8025@@ -39,8 +40,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
8026       mojo::PendingReceiver<blink::mojom::BlobURLToken> token) override;
8027
8028  private:
8029+  // Checks if the passed in url is a valid blob url for this blob url store.
8030+  // Returns false and reports a bad mojo message if not.
8031+  bool BlobUrlIsValid(const GURL& url, const char* method) const;
8032+
8033+  const url::Origin origin_;
8034   base::WeakPtr<BlobUrlRegistry> registry_;
8035-  BlobRegistryImpl::Delegate* delegate_;
8036
8037   std::set<GURL> urls_;
8038
8039diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
8040index 69428d0ade..52d17152b3 100644
8041--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
8042+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
8043@@ -17,7 +17,6 @@
8044 #include "storage/browser/blob/blob_impl.h"
8045 #include "storage/browser/blob/blob_storage_context.h"
8046 #include "storage/browser/blob/blob_url_registry.h"
8047-#include "storage/browser/test/mock_blob_registry_delegate.h"
8048 #include "testing/gtest/include/gtest/gtest.h"
8049
8050 using blink::mojom::BlobURLStore;
8051@@ -69,9 +68,9 @@ class BlobURLStoreImplTest : public testing::Test {
8052
8053   mojo::PendingRemote<BlobURLStore> CreateURLStore() {
8054     mojo::PendingRemote<BlobURLStore> result;
8055-    mojo::MakeSelfOwnedReceiver(std::make_unique<BlobURLStoreImpl>(
8056-                                    url_registry_.AsWeakPtr(), &delegate_),
8057-                                result.InitWithNewPipeAndPassReceiver());
8058+    mojo::MakeSelfOwnedReceiver(
8059+        std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr()),
8060+        result.InitWithNewPipeAndPassReceiver());
8061     return result;
8062   }
8063
8064@@ -101,15 +100,19 @@ class BlobURLStoreImplTest : public testing::Test {
8065   }
8066
8067   const std::string kId = "id";
8068-  const GURL kValidUrl = GURL("blob:id");
8069+  const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
8070+  const GURL kValidUrl = GURL("blob:" + kOrigin.Serialize() + "/id1");
8071+  const GURL kValidUrl2 = GURL("blob:" + kOrigin.Serialize() + "/id2");
8072   const GURL kInvalidUrl = GURL("bolb:id");
8073-  const GURL kFragmentUrl = GURL("blob:id#fragment");
8074+  const GURL kFragmentUrl = GURL(kValidUrl.spec() + "#fragment");
8075+  const url::Origin kWrongOrigin =
8076+      url::Origin::Create(GURL("https://test.com"));
8077+  const GURL kWrongOriginUrl = GURL("blob:" + kWrongOrigin.Serialize() + "/id");
8078
8079  protected:
8080   base::test::TaskEnvironment task_environment_;
8081   std::unique_ptr<BlobStorageContext> context_;
8082   BlobUrlRegistry url_registry_;
8083-  MockBlobRegistryDelegate delegate_;
8084   std::vector<std::string> bad_messages_;
8085 };
8086
8087@@ -118,7 +121,7 @@ TEST_F(BlobURLStoreImplTest, BasicRegisterRevoke) {
8088       CreateBlobFromString(kId, "hello world");
8089
8090   // Register a URL and make sure the URL keeps the blob alive.
8091-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8092+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8093   RegisterURL(&url_store, std::move(blob), kValidUrl);
8094
8095   blob = url_registry_.GetBlobFromUrl(kValidUrl);
8096@@ -146,15 +149,13 @@ TEST_F(BlobURLStoreImplTest, RegisterInvalidScheme) {
8097   EXPECT_EQ(1u, bad_messages_.size());
8098 }
8099
8100-TEST_F(BlobURLStoreImplTest, RegisterCantCommit) {
8101+TEST_F(BlobURLStoreImplTest, RegisterWrongOrigin) {
8102   mojo::PendingRemote<blink::mojom::Blob> blob =
8103       CreateBlobFromString(kId, "hello world");
8104
8105-  delegate_.can_commit_url_result = false;
8106-
8107   mojo::Remote<BlobURLStore> url_store(CreateURLStore());
8108-  RegisterURL(url_store.get(), std::move(blob), kValidUrl);
8109-  EXPECT_FALSE(url_registry_.GetBlobFromUrl(kValidUrl));
8110+  RegisterURL(url_store.get(), std::move(blob), kWrongOriginUrl);
8111+  EXPECT_FALSE(url_registry_.GetBlobFromUrl(kWrongOriginUrl));
8112   EXPECT_EQ(1u, bad_messages_.size());
8113 }
8114
8115@@ -169,14 +170,13 @@ TEST_F(BlobURLStoreImplTest, RegisterUrlFragment) {
8116 }
8117
8118 TEST_F(BlobURLStoreImplTest, ImplicitRevoke) {
8119-  const GURL kValidUrl2("blob:id2");
8120   mojo::Remote<blink::mojom::Blob> blob(
8121       CreateBlobFromString(kId, "hello world"));
8122   mojo::PendingRemote<blink::mojom::Blob> blob2;
8123   blob->Clone(blob2.InitWithNewPipeAndPassReceiver());
8124
8125   auto url_store =
8126-      std::make_unique<BlobURLStoreImpl>(url_registry_.AsWeakPtr(), &delegate_);
8127+      std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr());
8128   RegisterURL(url_store.get(), blob.Unbind(), kValidUrl);
8129   EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
8130   RegisterURL(url_store.get(), std::move(blob2), kValidUrl2);
8131@@ -192,8 +192,8 @@ TEST_F(BlobURLStoreImplTest, RevokeThroughDifferentURLStore) {
8132   mojo::PendingRemote<blink::mojom::Blob> blob =
8133       CreateBlobFromString(kId, "hello world");
8134
8135-  BlobURLStoreImpl url_store1(url_registry_.AsWeakPtr(), &delegate_);
8136-  BlobURLStoreImpl url_store2(url_registry_.AsWeakPtr(), &delegate_);
8137+  BlobURLStoreImpl url_store1(kOrigin, url_registry_.AsWeakPtr());
8138+  BlobURLStoreImpl url_store2(kOrigin, url_registry_.AsWeakPtr());
8139
8140   RegisterURL(&url_store1, std::move(blob), kValidUrl);
8141   EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
8142@@ -209,11 +209,9 @@ TEST_F(BlobURLStoreImplTest, RevokeInvalidScheme) {
8143   EXPECT_EQ(1u, bad_messages_.size());
8144 }
8145
8146-TEST_F(BlobURLStoreImplTest, RevokeCantCommit) {
8147-  delegate_.can_commit_url_result = false;
8148-
8149+TEST_F(BlobURLStoreImplTest, RevokeWrongOrigin) {
8150   mojo::Remote<BlobURLStore> url_store(CreateURLStore());
8151-  url_store->Revoke(kValidUrl);
8152+  url_store->Revoke(kWrongOriginUrl);
8153   url_store.FlushForTesting();
8154   EXPECT_EQ(1u, bad_messages_.size());
8155 }
8156@@ -229,7 +227,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
8157   mojo::PendingRemote<blink::mojom::Blob> blob =
8158       CreateBlobFromString(kId, "hello world");
8159
8160-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8161+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8162   RegisterURL(&url_store, std::move(blob), kValidUrl);
8163
8164   blob = ResolveURL(&url_store, kValidUrl);
8165@@ -244,7 +242,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
8166 }
8167
8168 TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
8169-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8170+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8171
8172   mojo::PendingRemote<blink::mojom::Blob> blob =
8173       ResolveURL(&url_store, kValidUrl);
8174@@ -254,7 +252,7 @@ TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
8175 }
8176
8177 TEST_F(BlobURLStoreImplTest, ResolveInvalidURL) {
8178-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8179+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8180
8181   mojo::PendingRemote<blink::mojom::Blob> blob =
8182       ResolveURL(&url_store, kInvalidUrl);
8183@@ -265,7 +263,7 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) {
8184   mojo::PendingRemote<blink::mojom::Blob> blob =
8185       CreateBlobFromString(kId, "hello world");
8186
8187-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8188+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8189   RegisterURL(&url_store, std::move(blob), kValidUrl);
8190
8191   mojo::Remote<network::mojom::URLLoaderFactory> factory;
8192@@ -291,7 +289,7 @@ TEST_F(BlobURLStoreImplTest, ResolveForNavigation) {
8193   mojo::PendingRemote<blink::mojom::Blob> blob =
8194       CreateBlobFromString(kId, "hello world");
8195
8196-  BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
8197+  BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
8198   RegisterURL(&url_store, std::move(blob), kValidUrl);
8199
8200   mojo::Remote<blink::mojom::BlobURLToken> token_remote;
8201diff --git a/third_party/angle/src/libANGLE/Framebuffer.cpp b/third_party/angle/src/libANGLE/Framebuffer.cpp
8202index 7d9856d15c..48cf822901 100644
8203--- a/third_party/angle/src/libANGLE/Framebuffer.cpp
8204+++ b/third_party/angle/src/libANGLE/Framebuffer.cpp
8205@@ -1925,6 +1925,14 @@ void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::Subject
8206             return;
8207         }
8208
8209+        // This can be triggered by freeing TextureStorage in D3D back-end.
8210+        if (message == angle::SubjectMessage::StorageReleased)
8211+        {
8212+            mDirtyBits.set(index);
8213+            invalidateCompletenessCache();
8214+            return;
8215+        }
8216+
8217         // This can be triggered by the GL back-end TextureGL class.
8218         ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
8219         return;
8220diff --git a/third_party/angle/src/libANGLE/Observer.h b/third_party/angle/src/libANGLE/Observer.h
8221index ae83677c77..bb2acd0210 100644
8222--- a/third_party/angle/src/libANGLE/Observer.h
8223+++ b/third_party/angle/src/libANGLE/Observer.h
8224@@ -54,6 +54,9 @@ enum class SubjectMessage
8225
8226     // Indicates an external change to the default framebuffer.
8227     SurfaceChanged,
8228+
8229+    // Indicates a Storage of back-end in gl::Texture has been released.
8230+    StorageReleased,
8231 };
8232
8233 // The observing class inherits from this interface class.
8234diff --git a/third_party/angle/src/libANGLE/Texture.cpp b/third_party/angle/src/libANGLE/Texture.cpp
8235index e90bfd7c7d..09aa3a5fb5 100644
8236--- a/third_party/angle/src/libANGLE/Texture.cpp
8237+++ b/third_party/angle/src/libANGLE/Texture.cpp
8238@@ -2236,6 +2236,15 @@ void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMess
8239                 mState.setImageDesc(TextureTarget::Buffer, 0, desc);
8240             }
8241             break;
8242+        case angle::SubjectMessage::StorageReleased:
8243+            // When the TextureStorage is released, it needs to update the
8244+            // RenderTargetCache of the Framebuffer attaching this Texture.
8245+            // This is currently only for D3D back-end. See http://crbug.com/1234829
8246+            if (index == rx::kTextureImageImplObserverMessageIndex)
8247+            {
8248+                onStateChange(angle::SubjectMessage::StorageReleased);
8249+            }
8250+            break;
8251         case angle::SubjectMessage::SubjectMapped:
8252         case angle::SubjectMessage::SubjectUnmapped:
8253         case angle::SubjectMessage::BindingChanged:
8254diff --git a/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
8255index 3a1b58b282..fc5ace1c05 100644
8256--- a/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
8257+++ b/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
8258@@ -710,6 +710,8 @@ angle::Result TextureD3D::releaseTexStorage(const gl::Context *context)
8259         return angle::Result::Continue;
8260     }
8261
8262+    onStateChange(angle::SubjectMessage::StorageReleased);
8263+
8264     auto err = mTexStorage->onDestroy(context);
8265     SafeDelete(mTexStorage);
8266     return err;
8267diff --git a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
8268index 8321bb60cd..7588a161eb 100644
8269--- a/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
8270+++ b/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
8271@@ -2179,28 +2179,35 @@ angle::Result GenerateInitialTextureData(
8272     const d3d11::DXGIFormatSize &dxgiFormatInfo =
8273         d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
8274
8275-    unsigned int rowPitch     = dxgiFormatInfo.pixelBytes * width;
8276-    unsigned int depthPitch   = rowPitch * height;
8277-    unsigned int maxImageSize = depthPitch * depth;
8278+    using CheckedSize        = angle::CheckedNumeric<size_t>;
8279+    CheckedSize rowPitch     = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
8280+    CheckedSize depthPitch   = rowPitch * CheckedSize(height);
8281+    CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
8282+
8283+    Context11 *context11 = GetImplAs<Context11>(context);
8284+    ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
8285
8286     angle::MemoryBuffer *scratchBuffer = nullptr;
8287-    ANGLE_CHECK_GL_ALLOC(GetImplAs<Context11>(context),
8288-                         context->getScratchBuffer(maxImageSize, &scratchBuffer));
8289+    ANGLE_CHECK_GL_ALLOC(context11,
8290+                         context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
8291
8292-    d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(), rowPitch,
8293-                                          depthPitch);
8294+    d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
8295+                                          rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
8296
8297     for (unsigned int i = 0; i < mipLevels; i++)
8298     {
8299         unsigned int mipWidth  = std::max(width >> i, 1U);
8300         unsigned int mipHeight = std::max(height >> i, 1U);
8301
8302-        unsigned int mipRowPitch   = dxgiFormatInfo.pixelBytes * mipWidth;
8303-        unsigned int mipDepthPitch = mipRowPitch * mipHeight;
8304+        using CheckedUINT         = angle::CheckedNumeric<UINT>;
8305+        CheckedUINT mipRowPitch   = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
8306+        CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
8307+
8308+        ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
8309
8310         outSubresourceData->at(i).pSysMem          = scratchBuffer->data();
8311-        outSubresourceData->at(i).SysMemPitch      = mipRowPitch;
8312-        outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch;
8313+        outSubresourceData->at(i).SysMemPitch      = mipRowPitch.ValueOrDie();
8314+        outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
8315     }
8316
8317     return angle::Result::Continue;
8318diff --git a/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
8319index f995fbd0c2..f2d2cf76bb 100644
8320--- a/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
8321+++ b/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
8322@@ -1283,6 +1283,10 @@ angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
8323     {
8324         releaseAndDeleteImageAndViews(contextVk);
8325     }
8326+    else if (mImage)
8327+    {
8328+        mImage->releaseStagingBuffer(contextVk->getRenderer());
8329+    }
8330
8331     const vk::Format &format = renderer->getFormat(internalformat);
8332     ANGLE_TRY(ensureImageAllocated(contextVk, format));
8333diff --git a/third_party/angle/src/libANGLE/validationES.cpp b/third_party/angle/src/libANGLE/validationES.cpp
8334index e49c3927d0..b2a2406a23 100644
8335--- a/third_party/angle/src/libANGLE/validationES.cpp
8336+++ b/third_party/angle/src/libANGLE/validationES.cpp
8337@@ -3923,6 +3923,12 @@ const char *ValidateDrawStates(const Context *context)
8338             {
8339                 return kVertexBufferBoundForTransformFeedback;
8340             }
8341+
8342+            // Validate that we are rendering with a linked program.
8343+            if (!program->isLinked())
8344+            {
8345+                return kProgramNotLinked;
8346+            }
8347         }
8348     }
8349
8350diff --git a/third_party/angle/src/tests/gl_tests/GLSLTest.cpp b/third_party/angle/src/tests/gl_tests/GLSLTest.cpp
8351index 851ccb4768..51b880df15 100644
8352--- a/third_party/angle/src/tests/gl_tests/GLSLTest.cpp
8353+++ b/third_party/angle/src/tests/gl_tests/GLSLTest.cpp
8354@@ -10493,6 +10493,54 @@ void main()
8355     GLuint program = CompileProgram(kVS, kFS);
8356     EXPECT_EQ(0u, program);
8357 }
8358+
8359+// Tests an unsuccessful re-link using glBindAttribLocation.
8360+TEST_P(GLSLTest_ES3, UnsuccessfulRelinkWithBindAttribLocation)
8361+{
8362+    // Make a simple program.
8363+    ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8364+
8365+    // Install the executable.
8366+    glUseProgram(testProgram);
8367+
8368+    // Re-link with a bad XFB varying and a bound attrib location.
8369+    const char *tfVaryings = "gl_FragColor";
8370+    glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
8371+    glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
8372+    glLinkProgram(testProgram);
8373+    GLint linkStatus = 999;
8374+    glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
8375+    ASSERT_GL_NO_ERROR();
8376+    ASSERT_EQ(linkStatus, GL_FALSE);
8377+
8378+    // Under normal GL this is not an error.
8379+    glDrawArrays(GL_TRIANGLES, 79, 16);
8380+    EXPECT_GL_NO_ERROR();
8381+}
8382+
8383+// Tests an unsuccessful re-link using glBindAttribLocation under WebGL.
8384+TEST_P(WebGL2GLSLTest, UnsuccessfulRelinkWithBindAttribLocation)
8385+{
8386+    // Make a simple program.
8387+    ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8388+
8389+    // Install the executable.
8390+    glUseProgram(testProgram);
8391+
8392+    // Re-link with a bad XFB varying and a bound attrib location.
8393+    const char *tfVaryings = "gl_FragColor";
8394+    glTransformFeedbackVaryings(testProgram, 1, &tfVaryings, GL_SEPARATE_ATTRIBS);
8395+    glBindAttribLocation(testProgram, 8, essl1_shaders::PositionAttrib());
8396+    glLinkProgram(testProgram);
8397+    GLint linkStatus = 999;
8398+    glGetProgramiv(testProgram, GL_LINK_STATUS, &linkStatus);
8399+    ASSERT_GL_NO_ERROR();
8400+    ASSERT_EQ(linkStatus, GL_FALSE);
8401+
8402+    // Under WebGL this is an error.
8403+    glDrawArrays(GL_TRIANGLES, 79, 16);
8404+    EXPECT_GL_ERROR(GL_INVALID_OPERATION);
8405+}
8406 }  // anonymous namespace
8407
8408 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(GLSLTest);
8409diff --git a/third_party/angle/src/tests/gl_tests/TextureTest.cpp b/third_party/angle/src/tests/gl_tests/TextureTest.cpp
8410index 23ea81694a..2dfcc0d00f 100644
8411--- a/third_party/angle/src/tests/gl_tests/TextureTest.cpp
8412+++ b/third_party/angle/src/tests/gl_tests/TextureTest.cpp
8413@@ -8151,6 +8151,26 @@ TEST_P(Texture2DTestES3, NonZeroBaseEmulatedClear)
8414     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
8415 }
8416
8417+// Test if the RenderTargetCache is updated when the TextureStorage object is freed
8418+TEST_P(Texture2DTestES3, UpdateRenderTargetCacheOnDestroyTexStorage)
8419+{
8420+    ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
8421+    const GLenum attachments[] = {GL_COLOR_ATTACHMENT0};
8422+
8423+    GLTexture tex;
8424+    GLFramebuffer fb;
8425+    glBindTexture(GL_TEXTURE_2D, tex);
8426+    glTexStorage2D(GL_TEXTURE_2D, 2, GL_RGBA8, 100, 1);
8427+    glBindFramebuffer(GL_FRAMEBUFFER, fb);
8428+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
8429+    glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments);
8430+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
8431+    drawQuad(drawRed, essl3_shaders::PositionAttrib(), 1.0f);
8432+    EXPECT_GL_NO_ERROR();
8433+
8434+    EXPECT_PIXEL_RECT_EQ(0, 0, 100, 1, GLColor::red);
8435+}
8436+
8437 // Draw a quad with an integer texture with a non-zero base level, and test that the color of the
8438 // texture is output.
8439 TEST_P(Texture2DIntegerTestES3, IntegerTextureNonZeroBaseLevel)
8440@@ -8750,6 +8770,73 @@ void main()
8441     glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
8442 }
8443
8444+class TextureChangeStorageUploadTest : public ANGLETest
8445+{
8446+  protected:
8447+    TextureChangeStorageUploadTest()
8448+    {
8449+        setWindowWidth(256);
8450+        setWindowHeight(256);
8451+        setConfigRedBits(8);
8452+        setConfigGreenBits(8);
8453+        setConfigBlueBits(8);
8454+        setConfigAlphaBits(8);
8455+    }
8456+
8457+    void testSetUp() override
8458+    {
8459+        mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
8460+        if (mProgram == 0)
8461+        {
8462+            FAIL() << "shader compilation failed.";
8463+        }
8464+
8465+        mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
8466+
8467+        glUseProgram(mProgram);
8468+
8469+        glClearColor(0, 0, 0, 0);
8470+        glClearDepthf(0.0);
8471+        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
8472+
8473+        glEnable(GL_BLEND);
8474+        glDisable(GL_DEPTH_TEST);
8475+
8476+        glGenTextures(1, &mTexture);
8477+        ASSERT_GL_NO_ERROR();
8478+    }
8479+
8480+    void testTearDown() override
8481+    {
8482+        glDeleteTextures(1, &mTexture);
8483+        glDeleteProgram(mProgram);
8484+    }
8485+
8486+    GLuint mProgram;
8487+    GLint mColorLocation;
8488+    GLuint mTexture;
8489+};
8490+
8491+// Verify that respecifying storage and re-uploading doesn't crash.
8492+TEST_P(TextureChangeStorageUploadTest, Basic)
8493+{
8494+    constexpr int kImageSize        = 8;  // 4 doesn't trip ASAN
8495+    constexpr int kSmallerImageSize = kImageSize / 2;
8496+    EXPECT_GT(kImageSize, kSmallerImageSize);
8497+    EXPECT_GT(kSmallerImageSize / 2, 0);
8498+
8499+    std::array<GLColor, kImageSize * kImageSize> kColor;
8500+
8501+    glBindTexture(GL_TEXTURE_2D, mTexture);
8502+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8503+                 kColor.data());
8504+    glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
8505+    // need partial update to sidestep optimizations that remove the full upload
8506+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
8507+                    GL_UNSIGNED_BYTE, kColor.data());
8508+    EXPECT_GL_NO_ERROR();
8509+}
8510+
8511 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
8512 // tests should be run against.
8513 #define ES2_EMULATE_COPY_TEX_IMAGE()                          \
8514@@ -8858,4 +8945,6 @@ ANGLE_INSTANTIATE_TEST_ES31(TextureBufferTestES31);
8515 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
8516 ANGLE_INSTANTIATE_TEST_ES31(CopyImageTestES31);
8517
8518+ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
8519+
8520 }  // anonymous namespace
8521diff --git a/third_party/blink/common/frame/user_activation_state.cc b/third_party/blink/common/frame/user_activation_state.cc
8522index 5ec774f5ce..5804a6b026 100644
8523--- a/third_party/blink/common/frame/user_activation_state.cc
8524+++ b/third_party/blink/common/frame/user_activation_state.cc
8525@@ -11,6 +11,23 @@ using blink::mojom::UserActivationNotificationType;
8526
8527 namespace blink {
8528
8529+namespace {
8530+
8531+// Indicates if |notification_type| should be considered restricted.  See
8532+// |LastActivationWasRestricted| for details.
8533+bool IsRestricted(UserActivationNotificationType notification_type) {
8534+  return notification_type == UserActivationNotificationType::
8535+                                  kExtensionMessagingBothPrivileged ||
8536+         notification_type == UserActivationNotificationType::
8537+                                  kExtensionMessagingSenderPrivileged ||
8538+         notification_type == UserActivationNotificationType::
8539+                                  kExtensionMessagingReceiverPrivileged ||
8540+         notification_type == UserActivationNotificationType::
8541+                                  kExtensionMessagingNeitherPrivileged;
8542+}
8543+
8544+}  // namespace
8545+
8546 // The expiry time should be long enough to allow network round trips even in a
8547 // very slow connection (to support xhr-like calls with user activation), yet
8548 // not too long to make an "unattended" page feel activated.
8549@@ -23,6 +40,7 @@ UserActivationState::UserActivationState()
8550 void UserActivationState::Activate(
8551     UserActivationNotificationType notification_type) {
8552   has_been_active_ = true;
8553+  last_activation_was_restricted_ = IsRestricted(notification_type);
8554   ActivateTransientState();
8555
8556   // Update states for UMA.
8557@@ -36,6 +54,7 @@ void UserActivationState::Activate(
8558
8559 void UserActivationState::Clear() {
8560   has_been_active_ = false;
8561+  last_activation_was_restricted_ = false;
8562   first_notification_type_ = UserActivationNotificationType::kNone;
8563   last_notification_type_ = UserActivationNotificationType::kNone;
8564   DeactivateTransientState();
8565@@ -70,6 +89,10 @@ bool UserActivationState::ConsumeIfActive() {
8566   return true;
8567 }
8568
8569+bool UserActivationState::LastActivationWasRestricted() const {
8570+  return last_activation_was_restricted_;
8571+}
8572+
8573 void UserActivationState::RecordPreconsumptionUma() const {
8574   if (!IsActiveInternal())
8575     return;
8576diff --git a/third_party/blink/public/common/frame/user_activation_state.h b/third_party/blink/public/common/frame/user_activation_state.h
8577index aa1a421c1c..380165d265 100644
8578--- a/third_party/blink/public/common/frame/user_activation_state.h
8579+++ b/third_party/blink/public/common/frame/user_activation_state.h
8580@@ -94,6 +94,9 @@ class BLINK_COMMON_EXPORT UserActivationState {
8581   // true and updates the transient state timestamp to "now".
8582   //
8583   // The |notification_type| parameter is used for histograms only.
8584+  //
8585+  // TODO(mustaq): When removing |notification_type|, explicitly pass
8586+  // |is_restricted| as a parameter here.
8587   void Activate(mojom::UserActivationNotificationType notification_type);
8588
8589   void Clear();
8590@@ -110,6 +113,21 @@ class BLINK_COMMON_EXPORT UserActivationState {
8591   // successfully consumed.
8592   bool ConsumeIfActive();
8593
8594+  // Indicates if the last user activation notification was restricted in
8595+  // nature.  This is a non-spec-compliant state, added only for compat reasons.
8596+  //
8597+  // Please don't add any new dependency to it!
8598+  //
8599+  // More details: A user activation on a frame is marked as restricted when the
8600+  // frame is neither an ancestor nor of the same-origin w.r.t. the frame where
8601+  // user interaction happened.  In other words, the restricted activation does
8602+  // not follow the tracking mechanism mentioned in the HTML spec and above.
8603+  // This non-standard activation in Chrome prevents breaking old extensions
8604+  // that (historically) expect a synthetic user activation to be available in
8605+  // an "unexposed" script-context (say in an extension's background script)
8606+  // after receiving an extension message under certain conditions.
8607+  bool LastActivationWasRestricted() const;
8608+
8609   // Records UMA stats related to consumption.  Must be called:
8610   // - before |ConsumeIfActive()| to record correct stats, and
8611   // - only once during consumption propagation to suppress over-counting.
8612@@ -126,6 +144,8 @@ class BLINK_COMMON_EXPORT UserActivationState {
8613   bool has_been_active_ = false;
8614   base::TimeTicks transient_state_expiry_time_;
8615
8616+  bool last_activation_was_restricted_ = false;
8617+
8618   // Tracks the expiry of |kInteraction| notification for UMA data.
8619   base::TimeTicks transient_state_expiry_time_for_interaction_;
8620
8621diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
8622index 382be0b3dd..c95a2e2551 100644
8623--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
8624+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
8625@@ -9,13 +9,6 @@ import "third_party/blink/public/mojom/blob/blob.mojom";
8626 import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
8627 import "third_party/blink/public/mojom/timing/worker_timing_container.mojom";
8628
8629-// Used for service worker navigation preload, to create
8630-// FetchEvent#preloadResponse.
8631-struct FetchEventPreloadHandle {
8632-  pending_remote<network.mojom.URLLoader> url_loader;
8633-  pending_receiver<network.mojom.URLLoaderClient> url_loader_client_receiver;
8634-};
8635-
8636 // Parameters used for dispatching a FetchEvent.
8637 struct DispatchFetchEventParams {
8638   // FetchEvent#request.
8639@@ -23,8 +16,9 @@ struct DispatchFetchEventParams {
8640
8641   // FetchEvent#clientId.
8642   string client_id;
8643+
8644   // FetchEvent#preloadResponse.
8645-  FetchEventPreloadHandle? preload_handle;
8646+  pending_receiver<network.mojom.URLLoaderClient>? preload_url_loader_client_receiver;
8647
8648   // This is currently null for navigation because it's still being implemented.
8649   // TODO(https://crbug.com/900700): Make this non-nullable when implementation
8650diff --git a/third_party/blink/public/mojom/webauthn/authenticator.mojom b/third_party/blink/public/mojom/webauthn/authenticator.mojom
8651index fd2d994705..25d66267c3 100644
8652--- a/third_party/blink/public/mojom/webauthn/authenticator.mojom
8653+++ b/third_party/blink/public/mojom/webauthn/authenticator.mojom
8654@@ -12,6 +12,12 @@ import "url/mojom/url.mojom";
8655 // credentials and use already-created credentials to get assertions.
8656 // See https://w3c.github.io/webauthn/.
8657
8658+// The maximum allowable list size for vectors of
8659+// `PublicKeyCredentialDescriptor` (i.e.
8660+// `PublicKeyCredentialCreationOptions.exclude_credentials` and
8661+// `PublicKeyCredentialRequestOptions.allow_credentials`).
8662+const uint32 kPublicKeyCredentialDescriptorListMaxSize = 64;
8663+
8664 enum AuthenticatorStatus {
8665   SUCCESS,
8666   PENDING_REQUEST,
8667diff --git a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
8668index 48e3e7ecec..ad64e9ba7f 100644
8669--- a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
8670+++ b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
8671@@ -31,8 +31,6 @@
8672 #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
8673 #define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
8674
8675-#include <memory>
8676-
8677 #include "base/memory/scoped_refptr.h"
8678 #include "base/time/time.h"
8679 #include "services/network/public/mojom/url_loader.mojom-shared.h"
8680@@ -54,14 +52,6 @@ namespace blink {
8681 class WebServiceWorkerContextProxy;
8682 class WebString;
8683
8684-// Used to pass the mojom struct blink.mojom.FetchEventPreloadHandle across the
8685-// boundary between //content and Blink.
8686-struct WebFetchEventPreloadHandle {
8687-  CrossVariantMojoRemote<network::mojom::URLLoaderInterfaceBase> url_loader;
8688-  CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
8689-      url_loader_client_receiver;
8690-};
8691-
8692 // WebServiceWorkerContextClient is a "client" of a service worker execution
8693 // context. This interface is implemented by the embedder and allows the
8694 // embedder to communicate with the service worker execution context.  It is
8695@@ -167,7 +157,8 @@ class WebServiceWorkerContextClient {
8696   virtual void SetupNavigationPreload(
8697       int fetch_event_id,
8698       const WebURL& url,
8699-      std::unique_ptr<WebFetchEventPreloadHandle> preload_handle) {}
8700+      CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
8701+          preload_url_loader_client_receiver) {}
8702
8703   // Called when we need to request to terminate this worker due to idle
8704   // timeout.
8705diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h
8706index 151d9e3de3..2355b99e90 100644
8707--- a/third_party/blink/public/web/web_local_frame.h
8708+++ b/third_party/blink/public/web/web_local_frame.h
8709@@ -777,20 +777,23 @@ class WebLocalFrame : public WebFrame {
8710
8711   // User activation -----------------------------------------------------------
8712
8713-  // See blink::LocalFrame::NotifyUserActivation().
8714+  // See |blink::LocalFrame::NotifyUserActivation()|.
8715   virtual void NotifyUserActivation(
8716       mojom::UserActivationNotificationType notification_type) = 0;
8717
8718-  // See blink::LocalFrame::HasStickyUserActivation().
8719+  // See |blink::Frame::HasStickyUserActivation()|.
8720   virtual bool HasStickyUserActivation() = 0;
8721
8722-  // See blink::LocalFrame::HasTransientUserActivation().
8723+  // See |blink::Frame::HasTransientUserActivation()|.
8724   virtual bool HasTransientUserActivation() = 0;
8725
8726-  // See blink::LocalFrame::ConsumeTransientUserActivation().
8727+  // See |blink::LocalFrame::ConsumeTransientUserActivation()|.
8728   virtual bool ConsumeTransientUserActivation(
8729       UserActivationUpdateSource update_source =
8730           UserActivationUpdateSource::kRenderer) = 0;
8731+
8732+  // See |blink::Frame::LastActivationWasRestricted()|.
8733+  virtual bool LastActivationWasRestricted() const = 0;
8734
8735   // Optimization Guide --------------------------------------------------------
8736
8737diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
8738index ea45c19829..02e5bc4ef1 100644
8739--- a/third_party/blink/renderer/core/animation/animation.cc
8740+++ b/third_party/blink/renderer/core/animation/animation.cc
8741@@ -2096,10 +2096,6 @@ bool Animation::Update(TimingUpdateReason reason) {
8742
8743   if (reason == kTimingUpdateForAnimationFrame) {
8744     if (idle || CalculateAnimationPlayState() == kFinished) {
8745-      // TODO(crbug.com/1029348): Per spec, we should have a microtask
8746-      // checkpoint right after the update cycle. Once this is fixed we should
8747-      // no longer need to force a synchronous resolution here.
8748-      AsyncFinishMicrotask();
8749       finished_ = true;
8750     }
8751   }
8752diff --git a/third_party/blink/renderer/core/animation/document_animations.cc b/third_party/blink/renderer/core/animation/document_animations.cc
8753index c7ed01c694..04ec203f21 100644
8754--- a/third_party/blink/renderer/core/animation/document_animations.cc
8755+++ b/third_party/blink/renderer/core/animation/document_animations.cc
8756@@ -44,6 +44,7 @@
8757 #include "third_party/blink/renderer/core/page/page.h"
8758 #include "third_party/blink/renderer/core/page/page_animator.h"
8759 #include "third_party/blink/renderer/platform/bindings/microtask.h"
8760+#include "third_party/blink/renderer/platform/heap/persistent.h"
8761
8762 namespace blink {
8763
8764@@ -254,10 +255,13 @@ void DocumentAnimations::RemoveReplacedAnimations(
8765
8766   // The list of animations for removal is constructed in reverse composite
8767   // ordering for efficiency. Flip the ordering to ensure that events are
8768-  // dispatched in composite order.
8769+  // dispatched in composite order.  Queue as a microtask so that the finished
8770+  // event is dispatched ahead of the remove event.
8771   for (auto it = animations_to_remove.rbegin();
8772        it != animations_to_remove.rend(); it++) {
8773-    (*it)->RemoveReplacedAnimation();
8774+    Animation* animation = *it;
8775+    Microtask::EnqueueMicrotask(WTF::Bind(&Animation::RemoveReplacedAnimation,
8776+                                          WrapWeakPersistent(animation)));
8777   }
8778 }
8779
8780diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
8781index b751822d19..715a830c65 100644
8782--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
8783+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.cc
8784@@ -173,6 +173,9 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
8785   if (!RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
8786     return;
8787
8788+  if (!node_)
8789+    return;
8790+
8791   auto* owner_node = GetFrameOwnerNode(node);
8792   if (owner_node)
8793     parent_frame_impl_ = MakeGarbageCollected<Impl>(owner_node, true);
8794@@ -215,6 +218,8 @@ DisplayLockUtilities::ScopedForcedUpdate::Impl::Impl(const Node* node,
8795 }
8796
8797 void DisplayLockUtilities::ScopedForcedUpdate::Impl::Destroy() {
8798+  if (!node_)
8799+    return;
8800   if (RuntimeEnabledFeatures::CSSContentVisibilityEnabled())
8801     node_->GetDocument().GetDisplayLockDocumentState().EndNodeForcedScope(this);
8802   if (parent_frame_impl_)
8803diff --git a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
8804index 6e6839e2c1..022ac073ca 100644
8805--- a/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
8806+++ b/third_party/blink/renderer/core/display_lock/display_lock_utilities.h
8807@@ -8,6 +8,7 @@
8808 #include "third_party/blink/renderer/core/core_export.h"
8809 #include "third_party/blink/renderer/core/display_lock/display_lock_context.h"
8810 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
8811+#include "third_party/blink/renderer/core/editing/frame_selection.h"
8812 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
8813
8814 namespace blink {
8815@@ -51,6 +52,8 @@ class CORE_EXPORT DisplayLockUtilities {
8816     friend void Document::EnsurePaintLocationDataValidForNode(
8817         const Node* node,
8818         DocumentUpdateReason reason);
8819+    friend VisibleSelection
8820+    FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated() const;
8821
8822     friend class DisplayLockContext;
8823
8824diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
8825index 40c41eae6f..ef07a29ca8 100644
8826--- a/third_party/blink/renderer/core/dom/document.cc
8827+++ b/third_party/blink/renderer/core/dom/document.cc
8828@@ -323,7 +323,6 @@
8829 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
8830 #include "third_party/blink/renderer/platform/network/content_security_policy_parsers.h"
8831 #include "third_party/blink/renderer/platform/network/http_parsers.h"
8832-#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
8833 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
8834 #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
8835 #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
8836@@ -577,43 +576,6 @@ uint64_t Document::global_tree_version_ = 0;
8837
8838 static bool g_threaded_parsing_enabled_for_testing = true;
8839
8840-class Document::NetworkStateObserver final
8841-    : public GarbageCollected<Document::NetworkStateObserver>,
8842-      public NetworkStateNotifier::NetworkStateObserver,
8843-      public ExecutionContextLifecycleObserver {
8844- public:
8845-  explicit NetworkStateObserver(ExecutionContext* context)
8846-      : ExecutionContextLifecycleObserver(context) {
8847-    online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
8848-        this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking));
8849-  }
8850-
8851-  void OnLineStateChange(bool on_line) override {
8852-    AtomicString event_name =
8853-        on_line ? event_type_names::kOnline : event_type_names::kOffline;
8854-    auto* window = To<LocalDOMWindow>(GetExecutionContext());
8855-    window->DispatchEvent(*Event::Create(event_name));
8856-    probe::NetworkStateChanged(window->GetFrame(), on_line);
8857-  }
8858-
8859-  void ContextDestroyed() override {
8860-    UnregisterAsObserver(GetExecutionContext());
8861-  }
8862-
8863-  void UnregisterAsObserver(ExecutionContext* context) {
8864-    DCHECK(context);
8865-    online_observer_handle_ = nullptr;
8866-  }
8867-
8868-  void Trace(Visitor* visitor) const override {
8869-    ExecutionContextLifecycleObserver::Trace(visitor);
8870-  }
8871-
8872- private:
8873-  std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
8874-      online_observer_handle_;
8875-};
8876-
8877 ExplicitlySetAttrElementsMap* Document::GetExplicitlySetAttrElementsMap(
8878     Element* element) {
8879   DCHECK(element);
8880@@ -2945,12 +2907,6 @@ void Document::Initialize() {
8881
8882   if (View())
8883     View()->DidAttachDocument();
8884-
8885-  // Observer(s) should not be initialized until the document is initialized /
8886-  // attached to a frame. Otherwise
8887-  // ExecutionContextLifecycleObserver::contextDestroyed wouldn't be fired.
8888-  network_state_observer_ =
8889-      MakeGarbageCollected<NetworkStateObserver>(GetExecutionContext());
8890 }
8891
8892 void Document::Shutdown() {
8893@@ -8162,7 +8118,6 @@ void Document::Trace(Visitor* visitor) const {
8894   visitor->Trace(intersection_observer_controller_);
8895   visitor->Trace(snap_coordinator_);
8896   visitor->Trace(property_registry_);
8897-  visitor->Trace(network_state_observer_);
8898   visitor->Trace(policy_);
8899   visitor->Trace(slot_assignment_engine_);
8900   visitor->Trace(viewport_data_);
8901diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
8902index b134657c84..dde3cfc634 100644
8903--- a/third_party/blink/renderer/core/dom/document.h
8904+++ b/third_party/blink/renderer/core/dom/document.h
8905@@ -1720,7 +1720,6 @@ class CORE_EXPORT Document : public ContainerNode,
8906                            BeforeMatchExpandedHiddenMatchableUkm);
8907   FRIEND_TEST_ALL_PREFIXES(TextFinderSimTest,
8908                            BeforeMatchExpandedHiddenMatchableUkmNoHandler);
8909-  class NetworkStateObserver;
8910
8911   friend class AXContext;
8912   void AddAXContext(AXContext*);
8913@@ -2112,8 +2111,6 @@ class CORE_EXPORT Document : public ContainerNode,
8914
8915   TaskHandle sensitive_input_edited_task_;
8916
8917-  Member<NetworkStateObserver> network_state_observer_;
8918-
8919   // |ukm_recorder_| and |source_id_| will allow objects that are part of
8920   // the document to record UKM.
8921   std::unique_ptr<ukm::UkmRecorder> ukm_recorder_;
8922diff --git a/third_party/blink/renderer/core/editing/frame_selection.cc b/third_party/blink/renderer/core/editing/frame_selection.cc
8923index d0133cc8da..f59557caeb 100644
8924--- a/third_party/blink/renderer/core/editing/frame_selection.cc
8925+++ b/third_party/blink/renderer/core/editing/frame_selection.cc
8926@@ -158,6 +158,10 @@ VisibleSelection FrameSelection::ComputeVisibleSelectionInDOMTreeDeprecated()
8927     const {
8928   // TODO(editing-dev): Hoist UpdateStyleAndLayout
8929   // to caller. See http://crbug.com/590369 for more details.
8930+  DisplayLockUtilities::ScopedForcedUpdate base_scope(
8931+      GetSelectionInDOMTree().Base().AnchorNode());
8932+  DisplayLockUtilities::ScopedForcedUpdate extent_scope(
8933+      GetSelectionInDOMTree().Extent().AnchorNode());
8934   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kSelection);
8935   return ComputeVisibleSelectionInDOMTree();
8936 }
8937diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h
8938index 485c1b1dd3..fa767917b2 100644
8939--- a/third_party/blink/renderer/core/frame/frame.h
8940+++ b/third_party/blink/renderer/core/frame/frame.h
8941@@ -212,6 +212,12 @@ class CORE_EXPORT Frame : public GarbageCollected<Frame> {
8942     return user_activation_state_.HasBeenActive();
8943   }
8944
8945+  // Returns if the last user activation for this frame was restricted in
8946+  // nature.
8947+  bool LastActivationWasRestricted() const {
8948+    return user_activation_state_.LastActivationWasRestricted();
8949+  }
8950+
8951   // Resets the user activation state of this frame.
8952   void ClearUserActivation() { user_activation_state_.Clear(); }
8953
8954diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
8955index 62dac665c1..b93ae92cb6 100644
8956--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
8957+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
8958@@ -128,6 +128,7 @@
8959 #include "third_party/blink/renderer/platform/bindings/script_state.h"
8960 #include "third_party/blink/renderer/platform/heap/heap.h"
8961 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
8962+#include "third_party/blink/renderer/platform/network/network_state_notifier.h"
8963 #include "third_party/blink/renderer/platform/scheduler/public/dummy_schedulers.h"
8964 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
8965 #include "third_party/blink/renderer/platform/timer.h"
8966@@ -163,6 +164,38 @@ bool ShouldRecordPostMessageIncomingFrameUkmEvent(
8967
8968 }  // namespace
8969
8970+class LocalDOMWindow::NetworkStateObserver final
8971+    : public GarbageCollected<LocalDOMWindow::NetworkStateObserver>,
8972+      public NetworkStateNotifier::NetworkStateObserver,
8973+      public ExecutionContextLifecycleObserver {
8974+ public:
8975+  explicit NetworkStateObserver(ExecutionContext* context)
8976+      : ExecutionContextLifecycleObserver(context) {}
8977+
8978+  void Initialize() {
8979+    online_observer_handle_ = GetNetworkStateNotifier().AddOnLineObserver(
8980+        this, GetExecutionContext()->GetTaskRunner(TaskType::kNetworking));
8981+  }
8982+
8983+  void OnLineStateChange(bool on_line) override {
8984+    AtomicString event_name =
8985+        on_line ? event_type_names::kOnline : event_type_names::kOffline;
8986+    auto* window = To<LocalDOMWindow>(GetExecutionContext());
8987+    window->DispatchEvent(*Event::Create(event_name));
8988+    probe::NetworkStateChanged(window->GetFrame(), on_line);
8989+  }
8990+
8991+  void ContextDestroyed() override { online_observer_handle_ = nullptr; }
8992+
8993+  void Trace(Visitor* visitor) const override {
8994+    ExecutionContextLifecycleObserver::Trace(visitor);
8995+  }
8996+
8997+ private:
8998+  std::unique_ptr<NetworkStateNotifier::NetworkStateObserverHandle>
8999+      online_observer_handle_;
9000+};
9001+
9002 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
9003     : DOMWindow(frame),
9004       ExecutionContext(V8PerIsolateData::MainThreadIsolate(), agent),
9005@@ -180,7 +213,9 @@ LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
9006       isolated_world_csp_map_(
9007           MakeGarbageCollected<
9008               HeapHashMap<int, Member<ContentSecurityPolicy>>>()),
9009-      token_(frame.GetLocalFrameToken()) {}
9010+      token_(frame.GetLocalFrameToken()),
9011+      network_state_observer_(
9012+          MakeGarbageCollected<NetworkStateObserver>(this)) {}
9013
9014 void LocalDOMWindow::BindContentSecurityPolicy() {
9015   DCHECK(!GetContentSecurityPolicy()->IsBound());
9016@@ -190,6 +225,7 @@ void LocalDOMWindow::BindContentSecurityPolicy() {
9017
9018 void LocalDOMWindow::Initialize() {
9019   GetAgent()->AttachContext(this);
9020+  network_state_observer_->Initialize();
9021 }
9022
9023 void LocalDOMWindow::ResetWindowAgent(WindowAgent* agent) {
9024@@ -2094,6 +2130,7 @@ void LocalDOMWindow::Trace(Visitor* visitor) const {
9025   visitor->Trace(spell_checker_);
9026   visitor->Trace(text_suggestion_controller_);
9027   visitor->Trace(isolated_world_csp_map_);
9028+  visitor->Trace(network_state_observer_);
9029   DOMWindow::Trace(visitor);
9030   ExecutionContext::Trace(visitor);
9031   Supplementable<LocalDOMWindow>::Trace(visitor);
9032diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
9033index 54799ba940..0ad3914d6b 100644
9034--- a/third_party/blink/renderer/core/frame/local_dom_window.h
9035+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
9036@@ -445,6 +445,8 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
9037                            LocalDOMWindow* source) override;
9038
9039  private:
9040+  class NetworkStateObserver;
9041+
9042   // Intentionally private to prevent redundant checks when the type is
9043   // already LocalDOMWindow.
9044   bool IsLocalDOMWindow() const override { return true; }
9045@@ -543,6 +545,9 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
9046   // this UKM is logged.
9047   // TODO(crbug.com/1112491): Remove when no longer needed.
9048   Deque<ukm::SourceId> post_message_ukm_recorded_source_ids_;
9049+
9050+  // Fire "online" and "offline" events.
9051+  Member<NetworkStateObserver> network_state_observer_;
9052 };
9053
9054 template <>
9055diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
9056index ce2ed9317c..3991250d8a 100644
9057--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
9058+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
9059@@ -651,6 +651,10 @@ bool WebLocalFrameImpl::ConsumeTransientUserActivation(
9060   return LocalFrame::ConsumeTransientUserActivation(GetFrame(), update_source);
9061 }
9062
9063+bool WebLocalFrameImpl::LastActivationWasRestricted() const {
9064+  return GetFrame()->LastActivationWasRestricted();
9065+}
9066+
9067 void WebLocalFrameImpl::SetOptimizationGuideHints(
9068     const WebOptimizationGuideHints& web_hints) {
9069   if (!GetFrame())
9070@@ -2071,6 +2075,16 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
9071       policy_container_receiver =
9072           policy_container_remote.InitWithNewEndpointAndPassReceiver();
9073
9074+  FramePolicy frame_policy = owner_element->GetFramePolicy();
9075+  // Documents create iframes, iframes host new documents. Both are associated
9076+  // with sandbox flags. They are required to be stricter or equal as we go
9077+  // down. The iframe owner element only returns the additional restrictions
9078+  // defined in the HTMLIFrameElement's sanbox attribute. It needs to be
9079+  // combined with the document's sandbox flags to get the frame's sandbox
9080+  // policy right.
9081+  frame_policy.sandbox_flags |=
9082+      GetFrame()->GetDocument()->GetExecutionContext()->GetSandboxFlags();
9083+
9084   // FIXME: Using subResourceAttributeName as fallback is not a perfect
9085   // solution. subResourceAttributeName returns just one attribute name. The
9086   // element might not have the attribute, and there might be other attributes
9087@@ -2080,8 +2094,7 @@ LocalFrame* WebLocalFrameImpl::CreateChildFrame(
9088           scope, name,
9089           owner_element->getAttribute(
9090               owner_element->SubResourceAttributeName()),
9091-          owner_element->GetFramePolicy(), owner_properties,
9092-          owner_element->OwnerType(),
9093+          std::move(frame_policy), owner_properties, owner_element->OwnerType(),
9094           WebPolicyContainerBindParams{std::move(policy_container_receiver)}));
9095   if (!webframe_child)
9096     return nullptr;
9097diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
9098index 7bd9fc4698..3c905f1dfd 100644
9099--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
9100+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
9101@@ -324,6 +324,7 @@ class CORE_EXPORT WebLocalFrameImpl final
9102   bool HasStickyUserActivation() override;
9103   bool HasTransientUserActivation() override;
9104   bool ConsumeTransientUserActivation(UserActivationUpdateSource) override;
9105+  bool LastActivationWasRestricted() const override;
9106   void SetOptimizationGuideHints(const WebOptimizationGuideHints&) override;
9107   void SetTargetToCurrentHistoryItem(const WebString& target) override;
9108   void UpdateCurrentHistoryItem() override;
9109diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
9110index cfa0b2e78b..ab26e9398f 100644
9111--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
9112+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
9113@@ -207,16 +207,27 @@ void HTMLIFrameElement::ParseAttribute(
9114       UpdateContainerPolicy();
9115     }
9116   } else if (name == html_names::kCspAttr) {
9117+    static const size_t kMaxLengthCSPAttribute = 4096;
9118     if (value && (value.Contains('\n') || value.Contains('\r') ||
9119                   !MatchesTheSerializedCSPGrammar(value.GetString()))) {
9120+      // TODO(antoniosartori): It would be safer to block loading iframes with
9121+      // invalid 'csp' attribute.
9122       required_csp_ = g_null_atom;
9123       GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
9124           mojom::blink::ConsoleMessageSource::kOther,
9125           mojom::blink::ConsoleMessageLevel::kError,
9126           "'csp' attribute is invalid: " + value));
9127-      return;
9128-    }
9129-    if (required_csp_ != value) {
9130+    } else if (value && value.length() > kMaxLengthCSPAttribute) {
9131+      // TODO(antoniosartori): It would be safer to block loading iframes with
9132+      // invalid 'csp' attribute.
9133+      required_csp_ = g_null_atom;
9134+      GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
9135+          mojom::blink::ConsoleMessageSource::kOther,
9136+          mojom::blink::ConsoleMessageLevel::kError,
9137+          String::Format("'csp' attribute too long. The max length for the "
9138+                         "'csp' attribute is %zu bytes.",
9139+                         kMaxLengthCSPAttribute)));
9140+    } else if (required_csp_ != value) {
9141       required_csp_ = value;
9142       CSPAttributeChanged();
9143       UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
9144diff --git a/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
9145index 99f25715af..4f3ee7e9cf 100644
9146--- a/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
9147+++ b/third_party/blink/renderer/core/html/parser/css_preload_scanner.cc
9148@@ -259,8 +259,7 @@ void CSSPreloadScanner::EmitRule(const SegmentedString& source) {
9149     auto request = PreloadRequest::CreateIfNeeded(
9150         fetch_initiator_type_names::kCSS, position, url,
9151         *predicted_base_element_url_, ResourceType::kCSSStyleSheet,
9152-        referrer_policy_, PreloadRequest::kBaseUrlIsReferrer,
9153-        ResourceFetcher::kImageNotImageSet, exclusion_info_);
9154+        referrer_policy_, ResourceFetcher::kImageNotImageSet, exclusion_info_);
9155     if (request) {
9156       // FIXME: Should this be including the charset in the preload request?
9157       requests_->push_back(std::move(request));
9158diff --git a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
9159index ea4b201b0a..99ab6cd142 100644
9160--- a/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
9161+++ b/third_party/blink/renderer/core/html/parser/html_preload_scanner.cc
9162@@ -321,9 +321,8 @@ class TokenPreloadScanner::StartTagScanner {
9163             : document_parameters.referrer_policy;
9164     auto request = PreloadRequest::CreateIfNeeded(
9165         InitiatorFor(tag_impl_), position, url_to_load_, predicted_base_url,
9166-        type.value(), referrer_policy, PreloadRequest::kDocumentIsReferrer,
9167-        is_image_set, exclusion_info, resource_width, client_hints_preferences,
9168-        request_type);
9169+        type.value(), referrer_policy, is_image_set, exclusion_info,
9170+        resource_width, client_hints_preferences, request_type);
9171     if (!request)
9172       return nullptr;
9173
9174diff --git a/third_party/blink/renderer/core/html/parser/html_resource_preloader_test.cc b/third_party/blink/renderer/core/html/parser/html_resource_preloader_test.cc
9175index 9dbe2ef393..ddd9f3de6a 100644
9176--- a/third_party/blink/renderer/core/html/parser/html_resource_preloader_test.cc
9177+++ b/third_party/blink/renderer/core/html/parser/html_resource_preloader_test.cc
9178@@ -58,10 +58,9 @@ class HTMLResourcePreloaderTest : public PageTestBase {
9179     auto preload_request = PreloadRequest::CreateIfNeeded(
9180         String(), TextPosition::MinimumPosition(), test_case.url,
9181         KURL(test_case.base_url), ResourceType::kImage,
9182-        network::mojom::ReferrerPolicy(), PreloadRequest::kDocumentIsReferrer,
9183-        ResourceFetcher::kImageNotImageSet, nullptr /* exclusion_info */,
9184-        FetchParameters::ResourceWidth(), ClientHintsPreferences(),
9185-        PreloadRequest::kRequestTypePreconnect);
9186+        network::mojom::ReferrerPolicy(), ResourceFetcher::kImageNotImageSet,
9187+        nullptr /* exclusion_info */, FetchParameters::ResourceWidth(),
9188+        ClientHintsPreferences(), PreloadRequest::kRequestTypePreconnect);
9189     DCHECK(preload_request);
9190     if (test_case.is_cors)
9191       preload_request->SetCrossOrigin(kCrossOriginAttributeAnonymous);
9192diff --git a/third_party/blink/renderer/core/html/parser/preload_request.cc b/third_party/blink/renderer/core/html/parser/preload_request.cc
9193index 73c57ab7c8..ec351968e7 100644
9194--- a/third_party/blink/renderer/core/html/parser/preload_request.cc
9195+++ b/third_party/blink/renderer/core/html/parser/preload_request.cc
9196@@ -61,7 +61,6 @@ std::unique_ptr<PreloadRequest> PreloadRequest::CreateIfNeeded(
9197     const KURL& base_url,
9198     ResourceType resource_type,
9199     const network::mojom::ReferrerPolicy referrer_policy,
9200-    ReferrerSource referrer_source,
9201     ResourceFetcher::IsImageSet is_image_set,
9202     const ExclusionInfo* exclusion_info,
9203     const FetchParameters::ResourceWidth& resource_width,
9204@@ -82,7 +81,7 @@ std::unique_ptr<PreloadRequest> PreloadRequest::CreateIfNeeded(
9205   return base::WrapUnique(new PreloadRequest(
9206       initiator_name, initiator_position, resource_url, base_url, resource_type,
9207       resource_width, client_hints_preferences, request_type, referrer_policy,
9208-      referrer_source, is_image_set));
9209+      is_image_set));
9210 }
9211
9212 Resource* PreloadRequest::Start(Document* document) {
9213@@ -98,9 +97,6 @@ Resource* PreloadRequest::Start(Document* document) {
9214
9215   ResourceRequest resource_request(url);
9216   resource_request.SetReferrerPolicy(referrer_policy_);
9217-  if (referrer_source_ == kBaseUrlIsReferrer) {
9218-    resource_request.SetReferrerString(base_url_.StrippedForUseAsReferrer());
9219-  }
9220
9221   resource_request.SetRequestContext(
9222       ResourceFetcher::DetermineRequestContext(resource_type_, is_image_set_));
9223diff --git a/third_party/blink/renderer/core/html/parser/preload_request.h b/third_party/blink/renderer/core/html/parser/preload_request.h
9224index 8f0d11c50f..9f64caa47e 100644
9225--- a/third_party/blink/renderer/core/html/parser/preload_request.h
9226+++ b/third_party/blink/renderer/core/html/parser/preload_request.h
9227@@ -62,8 +62,6 @@ class CORE_EXPORT PreloadRequest {
9228     kRequestTypeLinkRelPreload
9229   };
9230
9231-  enum ReferrerSource { kDocumentIsReferrer, kBaseUrlIsReferrer };
9232-
9233   static std::unique_ptr<PreloadRequest> CreateIfNeeded(
9234       const String& initiator_name,
9235       const TextPosition& initiator_position,
9236@@ -71,7 +69,6 @@ class CORE_EXPORT PreloadRequest {
9237       const KURL& base_url,
9238       ResourceType resource_type,
9239       const network::mojom::ReferrerPolicy referrer_policy,
9240-      ReferrerSource referrer_source,
9241       ResourceFetcher::IsImageSet is_image_set,
9242       const ExclusionInfo* exclusion_info,
9243       const FetchParameters::ResourceWidth& resource_width =
9244@@ -154,7 +151,6 @@ class CORE_EXPORT PreloadRequest {
9245                  const ClientHintsPreferences& client_hints_preferences,
9246                  RequestType request_type,
9247                  const network::mojom::ReferrerPolicy referrer_policy,
9248-                 ReferrerSource referrer_source,
9249                  ResourceFetcher::IsImageSet is_image_set)
9250       : initiator_name_(initiator_name),
9251         initiator_position_(initiator_position),
9252@@ -169,7 +165,6 @@ class CORE_EXPORT PreloadRequest {
9253         client_hints_preferences_(client_hints_preferences),
9254         request_type_(request_type),
9255         referrer_policy_(referrer_policy),
9256-        referrer_source_(referrer_source),
9257         from_insertion_scanner_(false),
9258         is_image_set_(is_image_set),
9259         is_lazy_load_image_enabled_(false) {}
9260@@ -191,7 +186,6 @@ class CORE_EXPORT PreloadRequest {
9261   const ClientHintsPreferences client_hints_preferences_;
9262   const RequestType request_type_;
9263   const network::mojom::ReferrerPolicy referrer_policy_;
9264-  const ReferrerSource referrer_source_;
9265   IntegrityMetadataSet integrity_metadata_;
9266   RenderBlockingBehavior render_blocking_behavior_ =
9267       RenderBlockingBehavior::kUnset;
9268diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
9269index e59adae120..d3fa773216 100644
9270--- a/third_party/blink/renderer/core/layout/layout_inline.cc
9271+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
9272@@ -574,15 +574,13 @@ void LayoutInline::SplitInlines(LayoutBlockFlow* from_block,
9273   // nest to a much greater depth (see bugzilla bug 13430) but for now we have a
9274   // limit. This *will* result in incorrect rendering, but the alternative is to
9275   // hang forever.
9276-  const unsigned kCMaxSplitDepth = 200;
9277   Vector<LayoutInline*> inlines_to_clone;
9278   LayoutInline* top_most_inline = this;
9279   for (LayoutObject* o = this; o != from_block; o = o->Parent()) {
9280     if (o->IsLayoutNGInsideListMarker())
9281       continue;
9282     top_most_inline = To<LayoutInline>(o);
9283-    if (inlines_to_clone.size() < kCMaxSplitDepth)
9284-      inlines_to_clone.push_back(top_most_inline);
9285+    inlines_to_clone.push_back(top_most_inline);
9286     // Keep walking up the chain to ensure |topMostInline| is a child of
9287     // |fromBlock|, to avoid assertion failure when |fromBlock|'s children are
9288     // moved to |toBlock| below.
9289diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
9290index c995ac8660..40d0b51332 100644
9291--- a/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
9292+++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.cc
9293@@ -11,6 +11,7 @@
9294 #include "skia/ext/image_operations.h"
9295 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
9296 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
9297+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
9298 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
9299 #include "third_party/blink/renderer/platform/image-decoders/image_frame.h"
9300 #include "third_party/blink/renderer/platform/image-decoders/segment_reader.h"
9301@@ -24,6 +25,80 @@
9302
9303 namespace blink {
9304
9305+namespace {
9306+
9307+void DecodeAndResizeImage(
9308+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
9309+    scoped_refptr<SegmentReader> data,
9310+    gfx::Size resize_dimensions,
9311+    CrossThreadOnceFunction<void(SkBitmap, double)> done_callback) {
9312+  auto notify_complete = [&](SkBitmap icon, double resize_scale) {
9313+    // This is needed so it can be moved cross-thread.
9314+    icon.setImmutable();
9315+    PostCrossThreadTask(*task_runner, FROM_HERE,
9316+                        CrossThreadBindOnce(std::move(done_callback),
9317+                                            std::move(icon), resize_scale));
9318+  };
9319+
9320+  std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
9321+      std::move(data), /* data_complete= */ true,
9322+      ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
9323+      ColorBehavior::TransformToSRGB());
9324+
9325+  if (!decoder) {
9326+    notify_complete(SkBitmap(), -1.0);
9327+    return;
9328+  }
9329+
9330+  ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
9331+
9332+  if (!image_frame) {
9333+    notify_complete(SkBitmap(), -1.0);
9334+    return;
9335+  }
9336+
9337+  SkBitmap decoded_icon = image_frame->Bitmap();
9338+  if (resize_dimensions.IsEmpty()) {
9339+    notify_complete(std::move(decoded_icon), 1.0);
9340+    return;
9341+  }
9342+
9343+  // If the icon is larger than |resize_dimensions| permits, we need to
9344+  // resize it as well. This can be done synchronously given that we're on a
9345+  // background thread already.
9346+  double scale = std::min(
9347+      static_cast<double>(resize_dimensions.width()) / decoded_icon.width(),
9348+      static_cast<double>(resize_dimensions.height()) / decoded_icon.height());
9349+
9350+  if (scale >= 1.0) {
9351+    notify_complete(std::move(decoded_icon), 1.0);
9352+    return;
9353+  }
9354+
9355+  int resized_width =
9356+      base::ranges::clamp(static_cast<int>(scale * decoded_icon.width()), 1,
9357+                  resize_dimensions.width());
9358+  int resized_height =
9359+      base::ranges::clamp(static_cast<int>(scale * decoded_icon.height()), 1,
9360+                  resize_dimensions.height());
9361+
9362+  // Use the RESIZE_GOOD quality allowing the implementation to pick an
9363+  // appropriate method for the resize. Can be increased to RESIZE_BETTER
9364+  // or RESIZE_BEST if the quality looks poor.
9365+  SkBitmap resized_icon = skia::ImageOperations::Resize(
9366+      decoded_icon, skia::ImageOperations::RESIZE_GOOD, resized_width,
9367+      resized_height);
9368+
9369+  if (resized_icon.isNull()) {
9370+    notify_complete(std::move(decoded_icon), 1.0);
9371+    return;
9372+  }
9373+
9374+  notify_complete(std::move(resized_icon), scale);
9375+}
9376+
9377+}  // namespace
9378+
9379 void ThreadedIconLoader::Start(
9380     ExecutionContext* execution_context,
9381     const ResourceRequestHead& resource_request,
9382@@ -83,87 +158,18 @@ void ThreadedIconLoader::DidFinishLoading(uint64_t resource_identifier) {
9383   worker_pool::PostTask(
9384       FROM_HERE,
9385       CrossThreadBindOnce(
9386-          &ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread,
9387-          WrapCrossThreadPersistent(this), std::move(task_runner),
9388-          SegmentReader::CreateFromSharedBuffer(std::move(data_))));
9389-}
9390-
9391-void ThreadedIconLoader::DecodeAndResizeImageOnBackgroundThread(
9392-    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
9393-    scoped_refptr<SegmentReader> data) {
9394-  DCHECK(task_runner);
9395-  DCHECK(data);
9396-
9397-  auto notify_complete = [&](double refactor_scale) {
9398-    PostCrossThreadTask(
9399-        *task_runner, FROM_HERE,
9400-        CrossThreadBindOnce(&ThreadedIconLoader::OnBackgroundTaskComplete,
9401-                            WrapCrossThreadPersistent(this), refactor_scale));
9402-  };
9403-
9404-  std::unique_ptr<ImageDecoder> decoder = ImageDecoder::Create(
9405-      std::move(data), /* data_complete= */ true,
9406-      ImageDecoder::kAlphaPremultiplied, ImageDecoder::kDefaultBitDepth,
9407-      ColorBehavior::TransformToSRGB());
9408-
9409-  if (!decoder) {
9410-    notify_complete(-1.0);
9411-    return;
9412-  }
9413-
9414-  ImageFrame* image_frame = decoder->DecodeFrameBufferAtIndex(0);
9415-
9416-  if (!image_frame) {
9417-    notify_complete(-1.0);
9418-    return;
9419-  }
9420-
9421-  decoded_icon_ = image_frame->Bitmap();
9422-  if (!resize_dimensions_) {
9423-    notify_complete(1.0);
9424-    return;
9425-  }
9426-
9427-  // If the icon is larger than |resize_dimensions_| permits, we need to resize
9428-  // it as well. This can be done synchronously given that we're on a
9429-  // background thread already.
9430-  double scale = std::min(
9431-      static_cast<double>(resize_dimensions_->width()) / decoded_icon_.width(),
9432-      static_cast<double>(resize_dimensions_->height()) /
9433-          decoded_icon_.height());
9434-
9435-  if (scale >= 1.0) {
9436-    notify_complete(1.0);
9437-    return;
9438-  }
9439-
9440-  int resized_width =
9441-      base::ClampToRange(static_cast<int>(scale * decoded_icon_.width()), 1,
9442-                         resize_dimensions_->width());
9443-  int resized_height =
9444-      base::ClampToRange(static_cast<int>(scale * decoded_icon_.height()), 1,
9445-                         resize_dimensions_->height());
9446-
9447-  // Use the RESIZE_GOOD quality allowing the implementation to pick an
9448-  // appropriate method for the resize. Can be increased to RESIZE_BETTER
9449-  // or RESIZE_BEST if the quality looks poor.
9450-  SkBitmap resized_icon = skia::ImageOperations::Resize(
9451-      decoded_icon_, skia::ImageOperations::RESIZE_GOOD, resized_width,
9452-      resized_height);
9453-
9454-  if (resized_icon.isNull()) {
9455-    notify_complete(1.0);
9456-    return;
9457-  }
9458-
9459-  decoded_icon_ = std::move(resized_icon);
9460-  notify_complete(scale);
9461+          &DecodeAndResizeImage, std::move(task_runner),
9462+          SegmentReader::CreateFromSharedBuffer(std::move(data_)),
9463+          resize_dimensions_ ? *resize_dimensions_ : gfx::Size(),
9464+          CrossThreadBindOnce(&ThreadedIconLoader::OnBackgroundTaskComplete,
9465+                              WrapCrossThreadWeakPersistent(this))));
9466 }
9467
9468-void ThreadedIconLoader::OnBackgroundTaskComplete(double resize_scale) {
9469+void ThreadedIconLoader::OnBackgroundTaskComplete(SkBitmap icon,
9470+                                                  double resize_scale) {
9471   if (stopped_)
9472     return;
9473-  std::move(icon_callback_).Run(std::move(decoded_icon_), resize_scale);
9474+  std::move(icon_callback_).Run(std::move(icon), resize_scale);
9475 }
9476
9477 void ThreadedIconLoader::DidFail(const ResourceError& error) {
9478diff --git a/third_party/blink/renderer/core/loader/threaded_icon_loader.h b/third_party/blink/renderer/core/loader/threaded_icon_loader.h
9479index 4497f329a0..41fba43ad7 100644
9480--- a/third_party/blink/renderer/core/loader/threaded_icon_loader.h
9481+++ b/third_party/blink/renderer/core/loader/threaded_icon_loader.h
9482@@ -18,7 +18,6 @@
9483 namespace blink {
9484
9485 class ResourceRequestHead;
9486-class SegmentReader;
9487
9488 // Utility class for loading, decoding, and potentially rescaling an icon on a
9489 // background thread. Note that icons are only downscaled and never upscaled.
9490@@ -52,11 +51,7 @@ class CORE_EXPORT ThreadedIconLoader final
9491   void Trace(Visitor* visitor) const override;
9492
9493  private:
9494-  void DecodeAndResizeImageOnBackgroundThread(
9495-      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
9496-      scoped_refptr<SegmentReader> data);
9497-
9498-  void OnBackgroundTaskComplete(double resize_scale);
9499+  void OnBackgroundTaskComplete(SkBitmap icon, double resize_scale);
9500
9501   Member<ThreadableLoader> threadable_loader_;
9502
9503@@ -64,9 +59,7 @@ class CORE_EXPORT ThreadedIconLoader final
9504   // of the image data starts.
9505   scoped_refptr<SharedBuffer> data_;
9506
9507-  // Accessed from main thread and background thread.
9508   base::Optional<gfx::Size> resize_dimensions_;
9509-  SkBitmap decoded_icon_;
9510
9511   IconCallback icon_callback_;
9512
9513diff --git a/third_party/blink/renderer/core/streams/build.gni b/third_party/blink/renderer/core/streams/build.gni
9514index 57a106353b..744d47f1a1 100644
9515--- a/third_party/blink/renderer/core/streams/build.gni
9516+++ b/third_party/blink/renderer/core/streams/build.gni
9517@@ -43,6 +43,7 @@ blink_core_sources_streams = [
9518   "transform_stream_default_controller.cc",
9519   "transform_stream_default_controller.h",
9520   "transform_stream_transformer.h",
9521+  "underlying_sink_base.cc",
9522   "underlying_sink_base.h",
9523   "underlying_source_base.cc",
9524   "underlying_source_base.h",
9525diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.cc b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
9526new file mode 100644
9527index 0000000000..a10d4f1865
9528--- /dev/null
9529+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
9530@@ -0,0 +1,29 @@
9531+// Copyright 2021 The Chromium Authors. All rights reserved.
9532+// Use of this source code is governed by a BSD-style license that can be
9533+// found in the LICENSE file.
9534+
9535+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
9536+
9537+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
9538+#include "v8/include/v8.h"
9539+
9540+namespace blink {
9541+
9542+ScriptPromise UnderlyingSinkBase::start(ScriptState* script_state,
9543+                                        ScriptValue controller,
9544+                                        ExceptionState& exception_state) {
9545+  controller_ = WritableStreamDefaultController::From(script_state, controller);
9546+  return start(script_state, controller_, exception_state);
9547+}
9548+
9549+ScriptValue UnderlyingSinkBase::type(ScriptState* script_state) const {
9550+  auto* isolate = script_state->GetIsolate();
9551+  return ScriptValue(isolate, v8::Undefined(isolate));
9552+}
9553+
9554+void UnderlyingSinkBase::Trace(Visitor* visitor) const {
9555+  visitor->Trace(controller_);
9556+  ScriptWrappable::Trace(visitor);
9557+}
9558+
9559+}  // namespace blink
9560diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.h b/third_party/blink/renderer/core/streams/underlying_sink_base.h
9561index 3b07d87f06..07ba729fc3 100644
9562--- a/third_party/blink/renderer/core/streams/underlying_sink_base.h
9563+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.h
9564@@ -6,16 +6,20 @@
9565 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
9566
9567 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
9568+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
9569 #include "third_party/blink/renderer/core/core_export.h"
9570-#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
9571 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
9572 #include "third_party/blink/renderer/platform/heap/visitor.h"
9573
9574+// Various files depend on us exporting this header.
9575+// TODO(ricea): Clean up the dependencies and remove this include.
9576+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
9577+
9578 namespace blink {
9579
9580 class ExceptionState;
9581-class ScriptValue;
9582 class ScriptState;
9583+class WritableStreamDefaultController;
9584
9585 class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
9586   DEFINE_WRAPPERTYPEINFO();
9587@@ -38,12 +42,8 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
9588                               ScriptValue reason,
9589                               ExceptionState&) = 0;
9590
9591-  ScriptPromise start(ScriptState* script_state,
9592-                      ScriptValue controller,
9593-                      ExceptionState& exception_state) {
9594-    controller_ = WritableStreamDefaultController::From(controller);
9595-    return start(script_state, controller_, exception_state);
9596-  }
9597+  ScriptPromise start(ScriptState*, ScriptValue controller, ExceptionState&);
9598+
9599   ScriptPromise write(ScriptState* script_state,
9600                       ScriptValue chunk,
9601                       ScriptValue controller,
9602@@ -52,10 +52,11 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
9603     return write(script_state, chunk, controller_, exception_state);
9604   }
9605
9606-  void Trace(Visitor* visitor) const override {
9607-    visitor->Trace(controller_);
9608-    ScriptWrappable::Trace(visitor);
9609-  }
9610+  // Returns a JavaScript "undefined" value. This is required by the
9611+  // WritableStream Create() method.
9612+  ScriptValue type(ScriptState*) const;
9613+
9614+  void Trace(Visitor*) const override;
9615
9616  protected:
9617   WritableStreamDefaultController* Controller() const { return controller_; }
9618diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.idl b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
9619index 8351141cbc..470eb527b1 100644
9620--- a/third_party/blink/renderer/core/streams/underlying_sink_base.idl
9621+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
9622@@ -14,4 +14,7 @@ interface UnderlyingSinkBase {
9623     [CallWith=ScriptState, RaisesException] Promise<void> write(any chunk, any controller);
9624     [CallWith=ScriptState, RaisesException] Promise<void> close();
9625     [CallWith=ScriptState, RaisesException] Promise<void> abort(any reason);
9626+
9627+    // This only exists to prevent Object.prototype.type being accessed.
9628+    [CallWith=ScriptState] readonly attribute any type;
9629 };
9630diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
9631index cc76647826..9f60d988f7 100644
9632--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
9633+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
9634@@ -21,10 +21,14 @@
9635 namespace blink {
9636
9637 WritableStreamDefaultController* WritableStreamDefaultController::From(
9638+    ScriptState* script_state,
9639     ScriptValue controller) {
9640-  DCHECK(controller.IsObject());
9641-  return V8WritableStreamDefaultController::ToImpl(
9642-      controller.V8Value().As<v8::Object>());
9643+  CHECK(controller.IsObject());
9644+  auto* controller_impl =
9645+      V8WritableStreamDefaultController::ToImplWithTypeCheck(
9646+          script_state->GetIsolate(), controller.V8Value().As<v8::Object>());
9647+  CHECK(controller_impl);
9648+  return controller_impl;
9649 }
9650
9651 // Only used internally. Not reachable from JavaScript.
9652diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
9653index 3351dcd694..8be6764217 100644
9654--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
9655+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
9656@@ -27,7 +27,7 @@ class CORE_EXPORT WritableStreamDefaultController final
9657   DEFINE_WRAPPERTYPEINFO();
9658
9659  public:
9660-  static WritableStreamDefaultController* From(ScriptValue);
9661+  static WritableStreamDefaultController* From(ScriptState*, ScriptValue);
9662
9663   // The JavaScript-exposed constructor throws automatically as no constructor
9664   // is specified in the IDL. This constructor is used internally during
9665diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
9666index 5482ce90e5..0ec3a20cff 100644
9667--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
9668+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
9669@@ -101,7 +101,7 @@ void ValidateResponseForPut(const Response* response,
9670     exception_state.ThrowTypeError("Vary header contains *");
9671     return;
9672   }
9673-  if (response->GetResponse()->InternalStatus() == 206) {
9674+  if (response->GetResponse()->Status() == 206) {
9675     exception_state.ThrowTypeError(
9676         "Partial response (status code 206) is unsupported");
9677     return;
9678diff --git a/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc b/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
9679index 79f4224fd9..3b5f52a9be 100644
9680--- a/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
9681+++ b/third_party/blink/renderer/modules/content_index/content_index_icon_loader.cc
9682@@ -26,6 +26,7 @@ constexpr base::TimeDelta kIconFetchTimeout = base::TimeDelta::FromSeconds(30);
9683 void FetchIcon(ExecutionContext* execution_context,
9684                const KURL& icon_url,
9685                const gfx::Size& icon_size,
9686+               ThreadedIconLoader* threaded_icon_loader,
9687                ThreadedIconLoader::IconCallback callback) {
9688   ResourceRequest resource_request(icon_url);
9689   resource_request.SetRequestContext(mojom::blink::RequestContextType::IMAGE);
9690@@ -34,7 +35,6 @@ void FetchIcon(ExecutionContext* execution_context,
9691   resource_request.SetPriority(ResourceLoadPriority::kMedium);
9692   resource_request.SetTimeoutInterval(kIconFetchTimeout);
9693
9694-  auto* threaded_icon_loader = MakeGarbageCollected<ThreadedIconLoader>();
9695   threaded_icon_loader->Start(execution_context, resource_request, icon_size,
9696                               std::move(callback));
9697 }
9698@@ -100,16 +100,21 @@ void ContentIndexIconLoader::Start(
9699     if (icon_url.IsEmpty())
9700       icon_url = KURL(image_resources[0].src);
9701
9702+    auto* threaded_icon_loader = MakeGarbageCollected<ThreadedIconLoader>();
9703     // |icons_ptr| is safe to use since it is owned by |barrier_closure|.
9704     FetchIcon(
9705-        execution_context, icon_url, icon_size,
9706+        execution_context, icon_url, icon_size, threaded_icon_loader,
9707         WTF::Bind(
9708             [](base::OnceClosure done_closure, Vector<SkBitmap>* icons_ptr,
9709-               SkBitmap icon, double resize_scale) {
9710+               ThreadedIconLoader* icon_loader, SkBitmap icon,
9711+               double resize_scale) {
9712               icons_ptr->push_back(std::move(icon));
9713               std::move(done_closure).Run();
9714             },
9715-            barrier_closure, WTF::Unretained(icons_ptr)));
9716+            barrier_closure, WTF::Unretained(icons_ptr),
9717+            // Pass |threaded_icon_loader| to the callback to make sure it
9718+            // doesn't get destroyed.
9719+            WrapPersistent(threaded_icon_loader)));
9720   }
9721 }
9722
9723diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
9724index 1061445c91..8aaf8511d0 100644
9725--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
9726+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
9727@@ -311,6 +311,11 @@ bool IsArrayBufferOrViewBelowSizeLimit(
9728       .IsValid();
9729 }
9730
9731+bool IsCredentialDescriptorListBelowSizeLimit(
9732+    const HeapVector<Member<PublicKeyCredentialDescriptor>>& list) {
9733+  return list.size() <= mojom::blink::kPublicKeyCredentialDescriptorListMaxSize;
9734+}
9735+
9736 DOMException* CredentialManagerErrorToDOMException(
9737     CredentialManagerError reason) {
9738   switch (reason) {
9739@@ -984,6 +989,16 @@ ScriptPromise CredentialsContainer::get(
9740           "RangeError"));
9741       return promise;
9742     }
9743+
9744+    if (!IsCredentialDescriptorListBelowSizeLimit(
9745+            options->publicKey()->allowCredentials())) {
9746+      resolver->Reject(
9747+          DOMException::Create("The `allowCredentials` attribute exceeds the "
9748+                               "maximum allowed size (64).",
9749+                               "RangeError"));
9750+      return promise;
9751+    }
9752+
9753     if (public_key_options->hasExtensions()) {
9754       if (public_key_options->extensions()->hasAppid()) {
9755         const auto& appid = public_key_options->extensions()->appid();
9756@@ -1259,10 +1274,19 @@ ScriptPromise CredentialsContainer::create(
9757       return promise;
9758     }
9759
9760+    if (!IsCredentialDescriptorListBelowSizeLimit(
9761+            options->publicKey()->excludeCredentials())) {
9762+      resolver->Reject(
9763+          DOMException::Create("The `excludeCredentials` attribute exceeds the "
9764+                              "maximum allowed size (64).",
9765+                              "RangeError"));
9766+      return promise;
9767+    }
9768+
9769     for (const auto& credential : options->publicKey()->excludeCredentials()) {
9770       if (!IsArrayBufferOrViewBelowSizeLimit(credential->id())) {
9771         resolver->Reject(DOMException::Create(
9772-            "The `excludedCredentials.id` attribute exceeds the maximum "
9773+            "The `excludeCredentials.id` attribute exceeds the maximum "
9774             "allowed size.",
9775             "RangeError"));
9776         return promise;
9777diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
9778index 9265e14be8..84a8825ec8 100644
9779--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
9780+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
9781@@ -1629,7 +1629,8 @@ void RTCPeerConnectionHandler::AddICECandidate(
9782        handler_weak_ptr = weak_factory_.GetWeakPtr(),
9783        tracker_weak_ptr =
9784            WrapCrossThreadWeakPersistent(peer_connection_tracker_.Get()),
9785-       candidate, persistent_request = WrapCrossThreadPersistent(request),
9786+       persistent_candidate = WrapCrossThreadPersistent(candidate),
9787+       persistent_request = WrapCrossThreadPersistent(request),
9788        callback_on_task_runner =
9789            std::move(callback_on_task_runner)](webrtc::RTCError result) {
9790         // Grab a snapshot of all the session descriptions. AddIceCandidate may
9791@@ -1657,7 +1658,7 @@ void RTCPeerConnectionHandler::AddICECandidate(
9792                 std::move(current_local_description),
9793                 std::move(pending_remote_description),
9794                 std::move(current_remote_description),
9795-                WrapCrossThreadPersistent(candidate), std::move(result),
9796+                std::move(persistent_candidate), std::move(result),
9797                 std::move(persistent_request)));
9798       });
9799 }
9800diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
9801index 862a8a747c..bed557e4f4 100644
9802--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
9803+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
9804@@ -1508,11 +1508,12 @@ void ServiceWorkerGlobalScope::StartFetchEvent(
9805       params->request->url.ElidedString().Utf8());
9806
9807   // Set up for navigation preload (FetchEvent#preloadResponse) if needed.
9808-  const bool navigation_preload_sent = !!params->preload_handle;
9809+  bool navigation_preload_sent = !!params->preload_url_loader_client_receiver;
9810   if (navigation_preload_sent) {
9811     To<ServiceWorkerGlobalScopeProxy>(ReportingProxy())
9812-        .SetupNavigationPreload(event_id, params->request->url,
9813-                                std::move(params->preload_handle));
9814+        .SetupNavigationPreload(
9815+            event_id, params->request->url,
9816+            std::move(params->preload_url_loader_client_receiver));
9817   }
9818
9819   ScriptState::Scope scope(ScriptController()->GetScriptState());
9820diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
9821index 397d579ed7..bae1f3ac2a 100644
9822--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
9823+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
9824@@ -258,14 +258,11 @@ bool ServiceWorkerGlobalScopeProxy::IsServiceWorkerGlobalScopeProxy() const {
9825 void ServiceWorkerGlobalScopeProxy::SetupNavigationPreload(
9826     int fetch_event_id,
9827     const KURL& url,
9828-    mojom::blink::FetchEventPreloadHandlePtr preload_handle) {
9829+    mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
9830+        preload_url_loader_client_receiver) {
9831   DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
9832-  auto web_preload_handle = std::make_unique<WebFetchEventPreloadHandle>();
9833-  web_preload_handle->url_loader = std::move(preload_handle->url_loader);
9834-  web_preload_handle->url_loader_client_receiver =
9835-      std::move(preload_handle->url_loader_client_receiver);
9836-  Client().SetupNavigationPreload(fetch_event_id, url,
9837-                                  std::move(web_preload_handle));
9838+  Client().SetupNavigationPreload(
9839+      fetch_event_id, url, std::move(preload_url_loader_client_receiver));
9840 }
9841
9842 void ServiceWorkerGlobalScopeProxy::RequestTermination(
9843diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
9844index 783dbe1919..d54a2449da 100644
9845--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
9846+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
9847@@ -129,7 +129,8 @@ class ServiceWorkerGlobalScopeProxy final : public WebServiceWorkerContextProxy,
9848   void SetupNavigationPreload(
9849       int fetch_event_id,
9850       const KURL& url,
9851-      mojom::blink::FetchEventPreloadHandlePtr preload_handle);
9852+      mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
9853+          preload_url_loader_client_receiver);
9854   void RequestTermination(WTF::CrossThreadOnceFunction<void(bool)> callback);
9855
9856   // Detaches this proxy object entirely from the outside world, clearing out
9857diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
9858index cf863b343b..f6a0dc5e5c 100644
9859--- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
9860+++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
9861@@ -37,6 +37,7 @@
9862 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
9863 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
9864 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
9865+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
9866 #include "third_party/fdlibm/ieee754.h"
9867
9868 #if defined(ARCH_CPU_X86_FAMILY)
9869@@ -133,7 +134,12 @@ float AudioParamTimeline::ExponentialRampAtTime(double t,
9870                                                 double time1,
9871                                                 float value2,
9872                                                 double time2) {
9873-  return value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
9874+  DCHECK(!std::isnan(value1) && std::isfinite(value1));
9875+  DCHECK(!std::isnan(value2) && std::isfinite(value2));
9876+
9877+  return (value1 == 0.0f || std::signbit(value1) != std::signbit(value2))
9878+      ? value1
9879+      : value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
9880 }
9881
9882 // Compute the value of a set target event at time t with the given event
9883@@ -998,6 +1004,8 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
9884     std::tie(value2, time2, next_event_type) =
9885         HandleCancelValues(event, next_event, value2, time2);
9886
9887+    DCHECK(!std::isnan(value1));
9888+    DCHECK(!std::isnan(value2));
9889     DCHECK_GE(time2, time1);
9890
9891     // |fillToEndFrame| is the exclusive upper bound of the last frame to be
9892@@ -1057,7 +1065,6 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
9893           value = event->Value();
9894           write_index =
9895               FillWithDefault(values, value, fill_to_frame, write_index);
9896-
9897           break;
9898         }
9899
9900@@ -1400,6 +1407,7 @@ AudioParamTimeline::HandleCancelValues(const ParamEvent* current_event,
9901               value2 = ExponentialRampAtTime(next_event->Time(), value1, time1,
9902                                              saved_event->Value(),
9903                                              saved_event->Time());
9904+              DCHECK(!std::isnan(value1));
9905               break;
9906             case ParamEvent::kSetValueCurve:
9907             case ParamEvent::kSetValueCurveEnd:
9908diff --git a/third_party/blink/renderer/modules/webgpu/dawn_callback.h b/third_party/blink/renderer/modules/webgpu/dawn_callback.h
9909index 812ac5b490..33f4aedcf6 100644
9910--- a/third_party/blink/renderer/modules/webgpu/dawn_callback.h
9911+++ b/third_party/blink/renderer/modules/webgpu/dawn_callback.h
9912@@ -17,8 +17,8 @@ namespace blink {
9913 // void* and passed to Dawn C callbacks.
9914 //
9915 // Example:
9916-//   DawnCallback<F>* callback =
9917-//     CreateDawnCallback(WTF::Bind(func, arg1));
9918+//   DawnOnceCallback<F>* callback =
9919+//     BindDawnOnceCallback(func, arg1);
9920 //
9921 //   // |someDawnFunction| expects callback function with arguments:
9922 //   //    Args... args, void* userdata.
9923@@ -26,81 +26,119 @@ namespace blink {
9924 //   GetProcs().someDawnFunction(
9925 //     callback->UnboundCallback(), callback->AsUserdata());
9926 template <typename Callback>
9927-class DawnCallback;
9928+class DawnCallbackBase;
9929+
9930+template <typename Callback>
9931+class DawnOnceCallback;
9932+
9933+template <typename Callback>
9934+class DawnRepeatingCallback;
9935
9936 template <template <typename> class BaseCallbackTemplate,
9937           typename R,
9938           typename... Args>
9939-class DawnCallback<BaseCallbackTemplate<R(Args...)>> {
9940+class DawnCallbackBase<BaseCallbackTemplate<R(Args...)>> {
9941   using BaseCallback = BaseCallbackTemplate<R(Args...)>;
9942-  using UnboundCallbackFunction = R (*)(Args..., void*);
9943
9944+  static constexpr bool is_once_callback =
9945+      std::is_same<BaseCallback, base::OnceCallback<R(Args...)>>::value;
9946+  static constexpr bool is_repeating_callback =
9947+      std::is_same<BaseCallback, base::RepeatingCallback<R(Args...)>>::value;
9948   static_assert(
9949-      std::is_same<BaseCallback, base::OnceCallback<R(Args...)>>::value ||
9950-          std::is_same<BaseCallback,
9951-                       base::RepeatingCallback<R(Args...)>>::value,
9952+      is_once_callback || is_repeating_callback,
9953       "Callback must be base::OnceCallback or base::RepeatingCallback");
9954
9955  public:
9956-  explicit DawnCallback(BaseCallback callback)
9957+  explicit DawnCallbackBase(BaseCallback callback)
9958       : callback_(std::move(callback)) {}
9959
9960+  void* AsUserdata() { return static_cast<void*>(this); }
9961+
9962+ protected:
9963+  using UnboundCallbackFunction = R (*)(Args..., void*);
9964+
9965+  static DawnCallbackBase* FromUserdata(void* userdata) {
9966+    return static_cast<DawnCallbackBase*>(userdata);
9967+  }
9968+
9969   R Run(Args... args) && {
9970+    static_assert(
9971+        is_once_callback,
9972+        "Run on a moved receiver must only be called on a once callback.");
9973     return std::move(callback_).Run(std::forward<Args>(args)...);
9974   }
9975
9976   R Run(Args... args) const& {
9977+    static_assert(is_repeating_callback,
9978+                  "Run on a unmoved receiver must only be called on a "
9979+                  "repeating callback.");
9980     return callback_.Run(std::forward<Args>(args)...);
9981   }
9982
9983-  void Reset() { callback_.Reset(); }
9984+ private:
9985+  BaseCallback callback_;
9986+};
9987+
9988+template <typename R, typename... Args>
9989+class DawnOnceCallback<R(Args...)>
9990+    : public DawnCallbackBase<base::OnceCallback<R(Args...)>> {
9991+  using BaseCallback = base::OnceCallback<R(Args...)>;
9992+
9993+ public:
9994+  using DawnCallbackBase<BaseCallback>::DawnCallbackBase;
9995
9996-  static R CallUnboundCallback(Args... args, void* handle) {
9997+  typename DawnCallbackBase<BaseCallback>::UnboundCallbackFunction
9998+  UnboundCallback() {
9999+    return CallUnboundOnceCallback;
10000+  }
10001+
10002+ private:
10003+  static R CallUnboundOnceCallback(Args... args, void* handle) {
10004     // After this non-repeating callback is run, it should delete itself.
10005     auto callback =
10006-        std::unique_ptr<DawnCallback>(DawnCallback::FromUserdata(handle));
10007+        std::unique_ptr<DawnOnceCallback>(static_cast<DawnOnceCallback*>(
10008+            DawnCallbackBase<BaseCallback>::FromUserdata(handle)));
10009     return std::move(*callback).Run(std::forward<Args>(args)...);
10010   }
10011+};
10012
10013-  static R CallUnboundRepeatingCallback(Args... args, void* handle) {
10014-    return DawnCallback::FromUserdata(handle)->Run(std::forward<Args>(args)...);
10015-  }
10016+template <typename R, typename... Args>
10017+class DawnRepeatingCallback<R(Args...)>
10018+    : public DawnCallbackBase<base::RepeatingCallback<R(Args...)>> {
10019+  using BaseCallback = base::RepeatingCallback<R(Args...)>;
10020
10021-  UnboundCallbackFunction UnboundCallback() { return CallUnboundCallback; }
10022+ public:
10023+  using DawnCallbackBase<BaseCallback>::DawnCallbackBase;
10024
10025-  UnboundCallbackFunction UnboundRepeatingCallback() {
10026+  typename DawnCallbackBase<BaseCallback>::UnboundCallbackFunction
10027+  UnboundCallback() {
10028     return CallUnboundRepeatingCallback;
10029   }
10030
10031-  void* AsUserdata() { return static_cast<void*>(this); }
10032-
10033-  static DawnCallback* FromUserdata(void* userdata) {
10034-    return static_cast<DawnCallback*>(userdata);
10035-  }
10036-
10037  private:
10038-  BaseCallback callback_;
10039+  static R CallUnboundRepeatingCallback(Args... args, void* handle) {
10040+    return static_cast<DawnRepeatingCallback*>(
10041+               DawnCallbackBase<BaseCallback>::FromUserdata(handle))
10042+        ->Run(std::forward<Args>(args)...);
10043+  }
10044 };
10045
10046-template <typename CallbackType>
10047-DawnCallback<CallbackType>* CreateDawnCallback(CallbackType cb) {
10048-  return new DawnCallback<CallbackType>(std::move(cb));
10049-}
10050-
10051 template <typename FunctionType, typename... BoundParameters>
10052-auto BindDawnCallback(FunctionType&& function,
10053-                      BoundParameters&&... bound_parameters) {
10054-  return CreateDawnCallback(
10055-      WTF::Bind(std::forward<FunctionType>(function),
10056-                std::forward<BoundParameters>(bound_parameters)...));
10057+auto BindDawnOnceCallback(FunctionType&& function,
10058+                          BoundParameters&&... bound_parameters) {
10059+  auto cb = WTF::Bind(std::forward<FunctionType>(function),
10060+                      std::forward<BoundParameters>(bound_parameters)...);
10061+  return new DawnOnceCallback<typename decltype(cb)::RunType>(std::move(cb));
10062 }
10063
10064 template <typename FunctionType, typename... BoundParameters>
10065-auto BindRepeatingDawnCallback(FunctionType&& function,
10066+auto BindDawnRepeatingCallback(FunctionType&& function,
10067                                BoundParameters&&... bound_parameters) {
10068-  return CreateDawnCallback(
10069+  auto cb =
10070       WTF::BindRepeating(std::forward<FunctionType>(function),
10071-                         std::forward<BoundParameters>(bound_parameters)...));
10072+                         std::forward<BoundParameters>(bound_parameters)...);
10073+  return std::make_unique<
10074+      DawnRepeatingCallback<typename decltype(cb)::RunType>>(std::move(cb));
10075 }
10076
10077 }  // namespace blink
10078diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
10079index c73982b6e0..f79c81b8ca 100644
10080--- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
10081+++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
10082@@ -152,8 +152,8 @@ ScriptPromise GPUBuffer::MapAsyncImpl(ScriptState* script_state,
10083
10084   // And send the command, leaving remaining validation to Dawn.
10085   auto* callback =
10086-      BindDawnCallback(&GPUBuffer::OnMapAsyncCallback, WrapPersistent(this),
10087-                       WrapPersistent(resolver));
10088+      BindDawnOnceCallback(&GPUBuffer::OnMapAsyncCallback, WrapPersistent(this),
10089+                           WrapPersistent(resolver));
10090
10091   GetProcs().bufferMapAsync(GetHandle(), mode, map_offset, map_size,
10092                             callback->UnboundCallback(),
10093diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
10094index 598f73bf45..c9dbf1567d 100644
10095--- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc
10096+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
10097@@ -69,13 +69,19 @@ GPUDevice::GPUDevice(ExecutionContext* execution_context,
10098           this,
10099           GetProcs().deviceGetDefaultQueue(GetHandle()))),
10100       lost_property_(MakeGarbageCollected<LostProperty>(execution_context)),
10101-      error_callback_(BindRepeatingDawnCallback(&GPUDevice::OnUncapturedError,
10102+      error_callback_(BindDawnRepeatingCallback(&GPUDevice::OnUncapturedError,
10103                                                 WrapWeakPersistent(this))),
10104-      lost_callback_(BindDawnCallback(&GPUDevice::OnDeviceLostError,
10105-                                      WrapWeakPersistent(this))) {
10106+      // Note: This is a *repeating* callback even though we expect it to only
10107+      // be called once. This is because it may be called *zero* times.
10108+      // Because it might never be called, the GPUDevice needs to own the
10109+      // allocation so it can be appropriately freed on destruction. Thus, the
10110+      // callback should not be a OnceCallback which self-deletes after it is
10111+      // called.
10112+      lost_callback_(BindDawnRepeatingCallback(&GPUDevice::OnDeviceLostError,
10113+                                               WrapWeakPersistent(this))) {
10114   DCHECK(dawn_device);
10115   GetProcs().deviceSetUncapturedErrorCallback(
10116-      GetHandle(), error_callback_->UnboundRepeatingCallback(),
10117+      GetHandle(), error_callback_->UnboundCallback(),
10118       error_callback_->AsUserdata());
10119   GetProcs().deviceSetDeviceLostCallback(GetHandle(),
10120                                          lost_callback_->UnboundCallback(),
10121@@ -84,6 +90,13 @@ GPUDevice::GPUDevice(ExecutionContext* execution_context,
10122   setLabel(descriptor->label());
10123 }
10124
10125+GPUDevice::~GPUDevice() {
10126+  // Clear the callbacks since we can't handle callbacks after finalization.
10127+  // error_callback_, logging_callback_, and lost_callback_ will be deleted.
10128+  GetProcs().deviceSetUncapturedErrorCallback(GetHandle(), nullptr, nullptr);
10129+  GetProcs().deviceSetDeviceLostCallback(GetHandle(), nullptr, nullptr);
10130+}
10131+
10132 void GPUDevice::InjectError(WGPUErrorType type, const char* message) {
10133   GetProcs().deviceInjectError(GetHandle(), type, message);
10134 }
10135@@ -133,12 +146,6 @@ void GPUDevice::OnUncapturedError(WGPUErrorType errorType,
10136 }
10137
10138 void GPUDevice::OnDeviceLostError(const char* message) {
10139-  // This function is called by a callback created by BindDawnCallback.
10140-  // Release the unique_ptr holding it since BindDawnCallback is self-deleting.
10141-  // This is stored as a unique_ptr because the lost callback may never be
10142-  // called.
10143-  lost_callback_.release();
10144-
10145   AddConsoleWarning(message);
10146
10147   if (lost_property_->GetState() == LostProperty::kPending) {
10148@@ -311,8 +318,8 @@ ScriptPromise GPUDevice::createComputePipelineAsync(
10149       AsDawnType(descriptor, &label, &computeStageDescriptor);
10150
10151   auto* callback =
10152-      BindDawnCallback(&GPUDevice::OnCreateComputePipelineAsyncCallback,
10153-                       WrapPersistent(this), WrapPersistent(resolver));
10154+      BindDawnOnceCallback(&GPUDevice::OnCreateComputePipelineAsyncCallback,
10155+                            WrapPersistent(this), WrapPersistent(resolver));
10156   GetProcs().deviceCreateComputePipelineAsync(GetHandle(), &dawn_desc,
10157                                               callback->UnboundCallback(),
10158                                               callback->AsUserdata());
10159@@ -366,8 +373,8 @@ ScriptPromise GPUDevice::popErrorScope(ScriptState* script_state) {
10160   ScriptPromise promise = resolver->Promise();
10161
10162   auto* callback =
10163-      BindDawnCallback(&GPUDevice::OnPopErrorScopeCallback,
10164-                       WrapPersistent(this), WrapPersistent(resolver));
10165+      BindDawnOnceCallback(&GPUDevice::OnPopErrorScopeCallback,
10166+                           WrapPersistent(this), WrapPersistent(resolver));
10167
10168   if (!GetProcs().devicePopErrorScope(GetHandle(), callback->UnboundCallback(),
10169                                       callback->AsUserdata())) {
10170diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.h b/third_party/blink/renderer/modules/webgpu/gpu_device.h
10171index 0dd29ab339..2613671b65 100644
10172--- a/third_party/blink/renderer/modules/webgpu/gpu_device.h
10173+++ b/third_party/blink/renderer/modules/webgpu/gpu_device.h
10174@@ -61,6 +61,7 @@ class GPUDevice final : public EventTargetWithInlineData,
10175                      GPUAdapter* adapter,
10176                      WGPUDevice dawn_device,
10177                      const GPUDeviceDescriptor* descriptor);
10178+  ~GPUDevice() override;
10179
10180   void Trace(Visitor* visitor) const override;
10181
10182@@ -154,15 +155,12 @@ class GPUDevice final : public EventTargetWithInlineData,
10183   Vector<String> feature_name_list_;
10184   Member<GPUQueue> queue_;
10185   Member<LostProperty> lost_property_;
10186-  std::unique_ptr<
10187-      DawnCallback<base::RepeatingCallback<void(WGPUErrorType, const char*)>>>
10188-      error_callback_;
10189+  std::unique_ptr<DawnRepeatingCallback<void(WGPUErrorType, const char*)>> error_callback_;
10190   // lost_callback_ is stored as a unique_ptr since it may never be called.
10191   // We need to be sure to free it on deletion of the device.
10192   // Inside OnDeviceLostError we'll release the unique_ptr to avoid a double
10193   // free.
10194-  std::unique_ptr<DawnCallback<base::OnceCallback<void(const char*)>>>
10195-      lost_callback_;
10196+  std::unique_ptr<DawnRepeatingCallback<void(const char*)>> lost_callback_;
10197
10198   static constexpr int kMaxAllowedConsoleWarnings = 500;
10199   int allowed_console_warnings_remaining_ = kMaxAllowedConsoleWarnings;
10200diff --git a/third_party/blink/renderer/modules/webgpu/gpu_fence.cc b/third_party/blink/renderer/modules/webgpu/gpu_fence.cc
10201index c384d4788e..2e1376b35e 100644
10202--- a/third_party/blink/renderer/modules/webgpu/gpu_fence.cc
10203+++ b/third_party/blink/renderer/modules/webgpu/gpu_fence.cc
10204@@ -44,8 +44,8 @@ ScriptPromise GPUFence::onCompletion(ScriptState* script_state,
10205   ScriptPromise promise = resolver->Promise();
10206
10207   auto* callback =
10208-      BindDawnCallback(&GPUFence::OnCompletionCallback, WrapPersistent(this),
10209-                       WrapPersistent(resolver));
10210+      BindDawnOnceCallback(&GPUFence::OnCompletionCallback, WrapPersistent(this),
10211+                            WrapPersistent(resolver));
10212
10213   GetProcs().fenceOnCompletion(GetHandle(), value, callback->UnboundCallback(),
10214                                callback->AsUserdata());
10215diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
10216index 5aa7ea019d..80235a96da 100644
10217--- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
10218+++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
10219@@ -207,8 +207,8 @@ ScriptPromise GPUQueue::onSubmittedWorkDone(ScriptState* script_state) {
10220   ScriptPromise promise = resolver->Promise();
10221
10222   auto* callback =
10223-      BindDawnCallback(&GPUQueue::OnWorkDoneCallback, WrapPersistent(this),
10224-                       WrapPersistent(resolver));
10225+      BindDawnOnceCallback(&GPUQueue::OnWorkDoneCallback, WrapPersistent(this),
10226+                           WrapPersistent(resolver));
10227
10228   GetProcs().queueOnSubmittedWorkDone(
10229       GetHandle(), 0u, callback->UnboundCallback(), callback->AsUserdata());
10230diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
10231index 034ded03d1..01cb98a111 100644
10232--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
10233+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
10234@@ -86,6 +86,8 @@ void HRTFDatabaseLoader::LoadTask() {
10235 void HRTFDatabaseLoader::LoadAsynchronously() {
10236   DCHECK(IsMainThread());
10237
10238+  MutexLocker locker(lock_);
10239+
10240   // m_hrtfDatabase and m_thread should both be unset because this should be a
10241   // new HRTFDatabaseLoader object that was just created by
10242   // createAndLoadAsynchronouslyIfNecessary and because we haven't started
10243@@ -122,6 +124,10 @@ void HRTFDatabaseLoader::CleanupTask(base::WaitableEvent* sync) {
10244 }
10245
10246 void HRTFDatabaseLoader::WaitForLoaderThreadCompletion() {
10247+  // We can lock this because this is called from either the main thread or
10248+  // the offline audio rendering thread.
10249+  MutexLocker locker(lock_);
10250+
10251   if (!thread_)
10252     return;
10253
10254diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
10255index 3ce476fa68..a94997b4f7 100644
10256--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
10257+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
10258@@ -64,8 +64,8 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
10259   // must be called from the audio thread.
10260   bool IsLoaded() { return Database(); }
10261
10262-  // waitForLoaderThreadCompletion() may be called more than once and is
10263-  // thread-safe.
10264+  // May be called from both main and audio thread, and also can be called more
10265+  // than once.
10266   void WaitForLoaderThreadCompletion();
10267
10268   // Returns the database or nullptr if the database doesn't yet exist.  Must
10269@@ -87,11 +87,10 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
10270   void LoadTask();
10271   void CleanupTask(base::WaitableEvent*);
10272
10273-  // Holding a m_lock is required when accessing m_hrtfDatabase since we access
10274-  // it from multiple threads.
10275+  // |lock_| MUST be held when accessing |hrtf_database_| or |thread_| because
10276+  // it can be accessed by multiple threads (e.g multiple AudioContexts).
10277   Mutex lock_;
10278   std::unique_ptr<HRTFDatabase> hrtf_database_;
10279-
10280   std::unique_ptr<Thread> thread_;
10281
10282   float database_sample_rate_;
10283diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
10284index 997893fef2..a946c28cac 100644
10285--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
10286+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
10287@@ -39,7 +39,9 @@
10288 #include "third_party/blink/renderer/platform/graphics/image.h"
10289 #include "third_party/blink/renderer/platform/platform_export.h"
10290 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
10291+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
10292 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
10293+#include "third_party/skia/include/core/SkBitmap.h"
10294 #include "third_party/skia/include/core/SkCanvas.h"
10295 #include "third_party/skia/include/core/SkColor.h"
10296 #include "third_party/skia/include/core/SkData.h"
10297@@ -197,4 +199,25 @@ PLATFORM_EXPORT sk_sp<SkData> TryAllocateSkData(size_t size);
10298
10299 }  // namespace blink
10300
10301+namespace WTF {
10302+
10303+// We define CrossThreadCopier<SKBitMap> here because we cannot include skia
10304+// headers in platform/wtf.
10305+template <>
10306+struct CrossThreadCopier<SkBitmap> {
10307+  STATIC_ONLY(CrossThreadCopier);
10308+
10309+  using Type = SkBitmap;
10310+  static SkBitmap Copy(const SkBitmap& bitmap) {
10311+    CHECK(bitmap.isImmutable() || bitmap.isNull()) << "Only immutable bitmaps can be transferred.";
10312+    return bitmap;
10313+  }
10314+  static SkBitmap Copy(SkBitmap&& bitmap) {
10315+    CHECK(bitmap.isImmutable() || bitmap.isNull()) << "Only immutable bitmaps can be transferred.";
10316+    return std::move(bitmap);
10317+  }
10318+};
10319+
10320+}  // namespace WTF
10321+
10322 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_SKIA_UTILS_H_
10323diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
10324index 3c445ddaa2..e367e9b803 100644
10325--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
10326+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
10327@@ -1877,6 +1877,19 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
10328   }
10329
10330   resource->VirtualTimePauser().UnpauseVirtualTime();
10331+
10332+  // A response should not serve partial content if it was not requested via a
10333+  // Range header: https://fetch.spec.whatwg.org/#main-fetch so keep it out
10334+  // of the preload cache in case of a non-206 response (which generates an
10335+  // error).
10336+  if (resource->GetResponse().GetType() ==
10337+          network::mojom::FetchResponseType::kOpaque &&
10338+      resource->GetResponse().HasRangeRequested() &&
10339+      !resource->GetResourceRequest().HttpHeaderFields().Contains(
10340+          net::HttpRequestHeaders::kRange)) {
10341+    RemovePreload(resource);
10342+  }
10343+
10344   if (type == kDidFinishLoading) {
10345     resource->Finish(response_end, freezable_task_runner_.get());
10346
10347diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_source.cc b/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
10348index a8dab81cc2..0f86e118f6 100644
10349--- a/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
10350+++ b/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
10351@@ -32,6 +32,7 @@
10352
10353 #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
10354 #include "third_party/blink/renderer/platform/audio/audio_bus.h"
10355+#include "third_party/blink/renderer/platform/heap/persistent.h"
10356 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
10357 #include "third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h"
10358 #include "third_party/blink/renderer/platform/wtf/assertions.h"
10359@@ -176,28 +177,17 @@ void MediaStreamSource::SetReadyState(ReadyState ready_state) {
10360     ready_state_ = ready_state;
10361
10362     // Observers may dispatch events which create and add new Observers;
10363-    // take a snapshot so as to safely iterate.
10364-    HeapVector<Member<Observer>> observers;
10365-    CopyToVector(observers_, observers);
10366-    for (auto observer : observers)
10367-      observer->SourceChangedState();
10368-
10369-    // setReadyState() will be invoked via the MediaStreamComponent::dispose()
10370-    // prefinalizer, allocating |observers|. Which means that |observers| will
10371-    // live until the next GC (but be unreferenced by other heap objects),
10372-    // _but_ it will potentially contain references to Observers that were
10373-    // GCed after the MediaStreamComponent prefinalizer had completed.
10374-    //
10375-    // So, if the next GC is a conservative one _and_ it happens to find
10376-    // a reference to |observers| when scanning the stack, we're in trouble
10377-    // as it contains references to now-dead objects.
10378-    //
10379-    // Work around this by explicitly clearing the vector backing store.
10380-    //
10381-    // TODO(sof): consider adding run-time checks that disallows this kind
10382-    // of dead object revivification by default.
10383-    for (wtf_size_t i = 0; i < observers.size(); ++i)
10384-      observers[i] = nullptr;
10385+    // take a snapshot so as to safely iterate. Wrap the observers in
10386+    // weak persistents to allow cancelling callbacks in case they are reclaimed
10387+    // until the callback is executed.
10388+    Vector<base::OnceClosure> observer_callbacks;
10389+    for (const auto& it : observers_) {
10390+      observer_callbacks.push_back(WTF::Bind(&Observer::SourceChangedState,
10391+                                             WrapWeakPersistent(it.Get())));
10392+    }
10393+    for (auto& observer_callback : observer_callbacks) {
10394+      std::move(observer_callback).Run();
10395+    }
10396   }
10397 }
10398
10399diff --git a/third_party/blink/web_tests/external/wpt/common/security-features/subresource/stylesheet.py b/third_party/blink/web_tests/external/wpt/common/security-features/subresource/stylesheet.py
10400index 29079af922..05db249250 100644
10401--- a/third_party/blink/web_tests/external/wpt/common/security-features/subresource/stylesheet.py
10402+++ b/third_party/blink/web_tests/external/wpt/common/security-features/subresource/stylesheet.py
10403@@ -23,6 +23,12 @@ def generate_payload(request, server_data):
10404             u"id": isomorphic_decode(request.GET[b"id"]),
10405             u"property": isomorphic_decode(request.GET[b"property"])}
10406
10407+    # A `'stylesheet-only'`-type stylesheet has no nested resources; this is
10408+    # useful in tests that cover referrers for stylesheet fetches (e.g. fetches
10409+    # triggered by `@import` statements).
10410+    elif type == b'stylesheet-only':
10411+        return u''
10412+
10413 def generate_import_rule(request, server_data):
10414     return u"@import url('%(url)s');" % {
10415         u"url": subresource.create_url(request, swap_origin=True,
10416diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
10417index a9ad787408..e0a31db8e2 100644
10418--- a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
10419+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
10420@@ -59,6 +59,9 @@
10421       { "name": "Wrong and dangerous value of `csp` should not trigger sending Sec-Required-CSP Header - report-to present",
10422         "csp": "script-src 'unsafe-inline'; report-to resources/dummy-report.php",
10423         "expected": null },
10424+      { "name": "Sec-Required-CSP is not sent if `csp` attribute is longer than 4096 bytes",
10425+        "csp": "style-src " + Array.from(Array(2044).keys()).map(i => 'a').join(' '),
10426+        "expected":  null },
10427     ];
10428
10429     tests.forEach(test => {
10430diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html
10431new file mode 100644
10432index 0000000000..9edca97568
10433--- /dev/null
10434+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/meter-selection-crash.html
10435@@ -0,0 +1,21 @@
10436+<!doctype HTML>
10437+<link rel=author href="mailto:vmpstr@chromium.org">
10438+<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
10439+<meta name="assert" content="meter, iframe, and selection API should not crash">
10440+
10441+<style>
10442+* {
10443+  all: initial;
10444+  content-visibility: hidden;
10445+}
10446+</style>
10447+
10448+<meter></meter><iframe id="frame"></iframe>
10449+<script>
10450+function runTest() {
10451+  var range_beadc = window.getSelection();
10452+  var elem1 = document.getElementById("frame");
10453+  range_beadc.setBaseAndExtent(elem1, 0, document.getElementById("none"), 0);
10454+}
10455+onload = runTest;
10456+</script>
10457diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
10458new file mode 100644
10459index 0000000000..65008f74ce
10460--- /dev/null
10461+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
10462@@ -0,0 +1,210 @@
10463+<!DOCTYPE html>
10464+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1245786">
10465+<style>
10466+  nav{ position: absolute; }
10467+  body > * { position: relative; }
10468+</style>
10469+<body>
10470+<span>
10471+<span>
10472+<span>
10473+<span>
10474+<span>
10475+<span>
10476+<span>
10477+<span>
10478+<span>
10479+<span>
10480+<span>
10481+<span>
10482+<span>
10483+<span>
10484+<span>
10485+<span>
10486+<span>
10487+<span>
10488+<span>
10489+<span>
10490+<span>
10491+<span>
10492+<span>
10493+<span>
10494+<span>
10495+<span>
10496+<span>
10497+<span>
10498+<span>
10499+<span>
10500+<span>
10501+<span>
10502+<span>
10503+<span>
10504+<span>
10505+<span>
10506+<span>
10507+<span>
10508+<span>
10509+<span>
10510+<span>
10511+<span>
10512+<span>
10513+<span>
10514+<span>
10515+<span>
10516+<span>
10517+<span>
10518+<span>
10519+<span>
10520+<span>
10521+<span>
10522+<span>
10523+<span>
10524+<span>
10525+<span>
10526+<span>
10527+<span>
10528+<span>
10529+<span>
10530+<span>
10531+<span>
10532+<span>
10533+<span>
10534+<span>
10535+<span>
10536+<span>
10537+<span>
10538+<span>
10539+<span>
10540+<span>
10541+<span>
10542+<span>
10543+<span>
10544+<span>
10545+<span>
10546+<span>
10547+<span>
10548+<span>
10549+<span>
10550+<span>
10551+<span>
10552+<span>
10553+<span>
10554+<span>
10555+<span>
10556+<span>
10557+<span>
10558+<span>
10559+<span>
10560+<span>
10561+<span>
10562+<span>
10563+<span>
10564+<span>
10565+<span>
10566+<span>
10567+<span>
10568+<span>
10569+<span>
10570+<span>
10571+<span>
10572+<span>
10573+<span>
10574+<span>
10575+<span>
10576+<span>
10577+<span>
10578+<span>
10579+<span>
10580+<span>
10581+<span>
10582+<span>
10583+<span>
10584+<span>
10585+<span>
10586+<span>
10587+<span>
10588+<span>
10589+<span>
10590+<span>
10591+<span>
10592+<span>
10593+<span>
10594+<span>
10595+<span>
10596+<span>
10597+<span>
10598+<span>
10599+<span>
10600+<span>
10601+<span>
10602+<span>
10603+<span>
10604+<span>
10605+<span>
10606+<span>
10607+<span>
10608+<span>
10609+<span>
10610+<span>
10611+<span>
10612+<span>
10613+<span>
10614+<span>
10615+<span>
10616+<span>
10617+<span>
10618+<span>
10619+<span>
10620+<span>
10621+<span>
10622+<span>
10623+<span>
10624+<span>
10625+<span>
10626+<span>
10627+<span>
10628+<span>
10629+<span>
10630+<span>
10631+<span>
10632+<span>
10633+<span>
10634+<span>
10635+<span>
10636+<span>
10637+<span>
10638+<span>
10639+<span>
10640+<span>
10641+<span>
10642+<span>
10643+<span>
10644+<span>
10645+<span>
10646+<span>
10647+<span>
10648+<span>
10649+<span>
10650+<span>
10651+<span>
10652+<span>
10653+<span>
10654+<span>
10655+<span>
10656+<span>
10657+<span>
10658+<span>
10659+<span>
10660+<span>
10661+<span>
10662+<span>
10663+<span>
10664+<span>
10665+<span>
10666+<span>
10667+<span>
10668+<span>
10669+<span>
10670+<span>
10671+<div>
10672+<nav>
10673diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
10674index eed44e0414..9f1ff98c65 100644
10675--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
10676+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
10677@@ -1,6 +1,7 @@
10678 // META: script=/common/get-host-info.sub.js
10679
10680 var redirectLocation = "cors-top.txt";
10681+const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
10682
10683 function testRedirect(origin, redirectStatus, redirectMode, corsMode) {
10684   var url = new URL("../resources/redirect.py", self.location);
10685@@ -47,4 +48,12 @@ for (var origin of ["same-origin", "cross-origin"]) {
10686   }
10687 }
10688
10689+promise_test(async (t) => {
10690+  const destination = `${ORIGIN}/common/blank.html`;
10691+  // We use /common/redirect.py intentionally, as we want a CORS error.
10692+  const url =
10693+    `${REMOTE_ORIGIN}/common/redirect.py?location=${destination}`;
10694+  await promise_rejects_js(t, TypeError,  fetch(url, { redirect: "manual" }));
10695+}, "manual redirect with a CORS error should be rejected");
10696+
10697 done();
10698diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
10699new file mode 100644
10700index 0000000000..a0058551d5
10701--- /dev/null
10702+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
10703@@ -0,0 +1,47 @@
10704+"""
10705+This generates a partial response for a 100-byte text file.
10706+"""
10707+import re
10708+
10709+from wptserve.utils import isomorphic_decode
10710+
10711+def main(request, response):
10712+    total_length = int(request.GET.first(b'length', b'100'))
10713+    partial_code = int(request.GET.first(b'partial', b'206'))
10714+    range_header = request.headers.get(b'Range', b'')
10715+
10716+    # Send a 200 if there is no range request
10717+    if not range_header:
10718+        to_send = ''.zfill(total_length)
10719+        response.headers.set(b"Content-Type", b"text/plain")
10720+        response.headers.set(b"Cache-Control", b"no-cache")
10721+        response.headers.set(b"Content-Length", total_length)
10722+        response.content = to_send
10723+        return
10724+
10725+    # Simple range parsing, requires specifically "bytes=xxx-xxxx"
10726+    range_header_match = re.search(r'^bytes=(\d*)-(\d*)$', isomorphic_decode(range_header))
10727+    start, end = range_header_match.groups()
10728+    start = int(start)
10729+    end = int(end) if end else total_length
10730+    length = end - start
10731+
10732+    # Error the request if the range goes beyond the length
10733+    if length <= 0 or end > total_length:
10734+        response.set_error(416, u"Range Not Satisfiable")
10735+        response.write()
10736+        return
10737+
10738+    # Generate a partial response of the requested length
10739+    to_send = ''.zfill(length)
10740+    response.headers.set(b"Content-Type", b"text/plain")
10741+    response.headers.set(b"Accept-Ranges", b"bytes")
10742+    response.headers.set(b"Cache-Control", b"no-cache")
10743+    response.status = partial_code
10744+
10745+    content_range = b"bytes %d-%d/%d" % (start, end, total_length)
10746+
10747+    response.headers.set(b"Content-Range", content_range)
10748+    response.headers.set(b"Content-Length", length)
10749+
10750+    response.content = to_send
10751diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
10752index 3680c0c471..b47823f03b 100644
10753--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
10754+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
10755@@ -12,7 +12,7 @@ async function broadcast(msg) {
10756   }
10757 }
10758
10759-addEventListener('fetch', event => {
10760+addEventListener('fetch', async event => {
10761   /** @type Request */
10762   const request = event.request;
10763   const url = new URL(request.url);
10764@@ -34,6 +34,11 @@ addEventListener('fetch', event => {
10765     case 'broadcast-accept-encoding':
10766       broadcastAcceptEncoding(event);
10767       return;
10768+    case 'record-media-range-request':
10769+      return recordMediaRangeRequest(event);
10770+    case 'use-media-range-request':
10771+      useMediaRangeRequest(event);
10772+      return;
10773   }
10774 });
10775
10776@@ -157,3 +162,57 @@ function broadcastAcceptEncoding(event) {
10777   // Just send back any response, it isn't important for the test.
10778   event.respondWith(new Response(''));
10779 }
10780+
10781+let rangeResponse = {};
10782+
10783+async function recordMediaRangeRequest(event) {
10784+  /** @type Request */
10785+  const request = event.request;
10786+  const url = new URL(request.url);
10787+  const urlParams = new URLSearchParams(url.search);
10788+  const size = urlParams.get("size");
10789+  const id = urlParams.get('id');
10790+  const key = 'size' + size;
10791+
10792+  if (key in rangeResponse) {
10793+    // Don't re-fetch ranges we already have.
10794+    const clonedResponse = rangeResponse[key].clone();
10795+    event.respondWith(clonedResponse);
10796+  } else if (event.request.headers.get("range") === "bytes=0-") {
10797+    // Generate a bogus 206 response to trigger subsequent range requests
10798+    // of the desired size.
10799+    const length = urlParams.get("length") + 100;
10800+    const body = "A".repeat(Number(size));
10801+    event.respondWith(new Response(body, {status: 206, headers: {
10802+      "Content-Type": "audio/mp4",
10803+      "Content-Range": `bytes 0-1/${length}`
10804+    }}));
10805+  } else if (event.request.headers.get("range") === `bytes=${Number(size)}-`) {
10806+    // Pass through actual range requests which will attempt to fetch up to the
10807+    // length in the original response which is bigger than the actual resource
10808+    // to make sure 206 and 416 responses are treated the same.
10809+    rangeResponse[key] = await fetch(event.request);
10810+
10811+    // Let the client know we have the range response for the given ID
10812+    broadcast({id});
10813+  } else {
10814+    event.respondWith(Promise.reject(Error("Invalid Request")));
10815+  }
10816+}
10817+
10818+function useMediaRangeRequest(event) {
10819+  /** @type Request */
10820+  const request = event.request;
10821+  const url = new URL(request.url);
10822+  const urlParams = new URLSearchParams(url.search);
10823+  const size = urlParams.get("size");
10824+  const key = 'size' + size;
10825+
10826+  // Send a clone of the range response to preload.
10827+  if (key in rangeResponse) {
10828+    const clonedResponse = rangeResponse[key].clone();
10829+    event.respondWith(clonedResponse);
10830+  } else {
10831+    event.respondWith(Promise.reject(Error("Invalid Request")));
10832+  }
10833+}
10834diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
10835index 16ed737f63..ad2853b33d 100644
10836--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
10837+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
10838@@ -8,6 +8,18 @@ function loadScript(url, { doc = document }={}) {
10839   })
10840 }
10841
10842+function preloadImage(url, { doc = document }={}) {
10843+  return new Promise((resolve, reject) => {
10844+    const preload = doc.createElement('link');
10845+    preload.rel = 'preload';
10846+    preload.as = 'image';
10847+    preload.onload = () => resolve();
10848+    preload.onerror = () => resolve();
10849+    preload.href = url;
10850+    doc.body.appendChild(preload);
10851+  })
10852+}
10853+
10854 /**
10855  *
10856  * @param {Document} document
10857diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
10858index 134b0a7abd..a9577f0172 100644
10859--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
10860+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
10861@@ -4,6 +4,7 @@ PASS Defer range header passthrough tests to service worker
10862 PASS Ranged response not allowed following no-cors ranged request
10863 PASS Non-opaque ranged response executed
10864 FAIL Accept-Encoding should not appear in a service worker assert_equals: Accept-Encoding should not be set for media expected (object) null but got (string) "identity;q=1, *;q=0"
10865+PASS Opaque range preload successes and failures should be indistinguishable
10866 PASS Range headers correctly preserved
10867 PASS Range headers correctly removed
10868 PASS Headers correctly filtered
10869diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
10870index 76f80e9416..42e4ac6d75 100644
10871--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
10872+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
10873@@ -149,3 +149,78 @@ promise_test(async t => {
10874
10875   assert_equals((await audioBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for media");
10876 }, `Accept-Encoding should not appear in a service worker`);
10877+
10878+promise_test(async t => {
10879+  const scope = BASE_SCOPE + Math.random();
10880+  await setupRegistration(t, scope);
10881+  const iframe = await with_iframe(scope);
10882+  const w = iframe.contentWindow;
10883+  const length = 100;
10884+  const count = 3;
10885+  const counts = {};
10886+
10887+  // test a single range request size
10888+  async function testSizedRange(size, partialResponseCode) {
10889+    const rangeId = Math.random() + '';
10890+    const rangeBroadcast = awaitMessage(w.navigator.serviceWorker, rangeId);
10891+
10892+    // Create a bogus audo element to trick the browser into sending
10893+    // cross-origin range requests that can be manipulated by the service worker.
10894+    const sound_url = new URL('partial-text.py', w.location);
10895+    sound_url.hostname = REMOTE_HOST;
10896+    sound_url.searchParams.set('action', 'record-media-range-request');
10897+    sound_url.searchParams.set('length', length);
10898+    sound_url.searchParams.set('size', size);
10899+    sound_url.searchParams.set('partial', partialResponseCode);
10900+    sound_url.searchParams.set('id', rangeId);
10901+    appendAudio(w.document, sound_url);
10902+
10903+    // wait for the range requests to happen
10904+    await rangeBroadcast;
10905+
10906+    // Create multiple preload requests and count the number of resource timing
10907+    // entries that get created to make sure 206 and 416 range responses are treated
10908+    // the same.
10909+    const url = new URL('partial-text.py', w.location);
10910+    url.searchParams.set('action', 'use-media-range-request');
10911+    url.searchParams.set('size', size);
10912+    counts['size' + size] = 0;
10913+    for (let i = 0; i < count; i++) {
10914+      await preloadImage(url, { doc: w.document });
10915+    }
10916+  }
10917+
10918+  // Test range requests from 1 smaller than the correct size to 1 larger than
10919+  // the correct size to exercise the various permutations using the default 206
10920+  // response code for successful range requests.
10921+  for (let size = length - 1; size <= length + 1; size++) {
10922+    await testSizedRange(size, '206');
10923+  }
10924+
10925+  // Test a successful range request using a 200 response.
10926+  await testSizedRange(length - 2, '200');
10927+
10928+  // Check the resource timing entries and count the reported number of fetches of each type
10929+  const resources = w.performance.getEntriesByType("resource");
10930+  for (const entry of resources) {
10931+    const url = new URL(entry.name);
10932+    if (url.searchParams.has('action') &&
10933+        url.searchParams.get('action') == 'use-media-range-request' &&
10934+        url.searchParams.has('size')) {
10935+      counts['size' + url.searchParams.get('size')]++;
10936+    }
10937+  }
10938+
10939+  // Make sure there are a non-zero number of preload requests and they are all the same
10940+  let counts_valid = true;
10941+  const first = 'size' + (length - 2);
10942+  for (let size = length - 2; size <= length + 1; size++) {
10943+    let key = 'size' + size;
10944+    if (!(key in counts) || counts[key] <= 0 || counts[key] != counts[first]) {
10945+      counts_valid = false;
10946+      break;
10947+    }
10948+  }
10949+
10950+  assert_true(counts_valid, `Opaque range request preloads were different for error and success`);
10951+}, `Opaque range preload successes and failures should be indistinguishable`);
10952diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/popup-from-initial-empty-sandboxed-document.window.js b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/popup-from-initial-empty-sandboxed-document.window.js
10953new file mode 100644
10954index 0000000000..e70a52ae8a
10955--- /dev/null
10956+++ b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/popup-from-initial-empty-sandboxed-document.window.js
10957@@ -0,0 +1,49 @@
10958+// META: timeout=long
10959+// META: script=/common/utils.js
10960+// META: script=/common/dispatcher/dispatcher.js
10961+
10962+// Regression test for: https://crbug.com/1256822.
10963+//
10964+// From a sandboxed iframe allowing popups, scripts, and same-origin. Open a
10965+// popup using the WindowProxy of a new iframe that is still on the initial
10966+// empty document. Check that the sandbox flags are properly inherited.
10967+
10968+const executorUrl = uuid =>
10969+  (new URL(`./resources/executor.html?uuid=${uuid}`, window.location)).href;
10970+
10971+// Return true if the execution context is sandboxed.
10972+const isSandboxed = () => {
10973+  try {
10974+    // Setting document.domain in sandboxed document throw errors.
10975+    document.domain = document.domain;
10976+    return false;
10977+  } catch (error) {
10978+    return true;
10979+  }
10980+}
10981+
10982+promise_test(async test => {
10983+  // 1. Create a sandboxed iframe, allowing popups, same-origin and scripts.
10984+  const iframe_token = token();
10985+  const iframe_document = new RemoteContext(iframe_token);
10986+  const iframe_url = executorUrl(iframe_token);
10987+  const iframe = document.createElement("iframe");
10988+  iframe.sandbox = "allow-same-origin allow-scripts allow-popups";
10989+  iframe.src = iframe_url;
10990+  document.body.appendChild(iframe);
10991+  assert_true(await iframe_document.execute_script(isSandboxed),
10992+    "iframe is sandboxed");
10993+
10994+  // 2. From the sandboxed iframe, create an empty iframe, and open a popup
10995+  //    using it's WindowProxy. The popup must inherit sandbox flags.
10996+  const popup_token = token();
10997+  const popup_document = new RemoteContext(popup_token);
10998+  const popup_url = executorUrl(popup_token);
10999+  iframe_document.execute_script((popup_url) => {
11000+    let iframe = document.createElement("iframe");
11001+    iframe.name = "iframe_name";
11002+    document.body.appendChild(iframe);
11003+    iframe_name.open(popup_url);
11004+  }, [popup_url]);
11005+  assert_true(await popup_document.execute_script(isSandboxed), "popup is sandboxed");
11006+});
11007diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/execute-postmessage.html b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/execute-postmessage.html
11008new file mode 100644
11009index 0000000000..89bd268f9c
11010--- /dev/null
11011+++ b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/execute-postmessage.html
11012@@ -0,0 +1,5 @@
11013+<script>
11014+  // Execute arbitrary code from somewhere else, via postMessage.
11015+  window.addEventListener("message", event => eval(event.data));
11016+  window.opener.postMessage("ready", "*");
11017+</script>
11018diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/executor.html b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/executor.html
11019index 89bd268f9c..67b9783fec 100644
11020--- a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/executor.html
11021+++ b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/resources/executor.html
11022@@ -1,5 +1,7 @@
11023+<script src="/common/dispatcher/dispatcher.js"></script>
11024 <script>
11025-  // Execute arbitrary code from somewhere else, via postMessage.
11026-  window.addEventListener("message", event => eval(event.data));
11027-  window.opener.postMessage("ready", "*");
11028+  const params = new URLSearchParams(window.location.search);
11029+  const uuid = params.get("uuid");
11030+  const executor = new Executor(uuid);
11031+  executor.execute();
11032 </script>
11033diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/window-open-blank-from-different-initiator.html b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/window-open-blank-from-different-initiator.html
11034index 28345d2a8e..91817c3db4 100644
11035--- a/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/window-open-blank-from-different-initiator.html
11036+++ b/third_party/blink/web_tests/external/wpt/html/browsers/sandboxing/window-open-blank-from-different-initiator.html
11037@@ -30,7 +30,7 @@ const runTest = (description, createNewPopup) => {
11038   promise_test(async test => {
11039     // Open a same-origin window with a different CSP.
11040     const executor_path =
11041-      "/html/browsers/sandboxing/resources/executor.html?pipe=";
11042+      "/html/browsers/sandboxing/resources/execute-postmessage.html?pipe=";
11043     const csp = "|header(Content-Security-Policy, " +
11044                 "sandbox" +
11045                 " allow-scripts" +
11046diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url-from-preload.tentative.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url-from-preload.tentative.html
11047new file mode 100644
11048index 0000000000..4d2228c9a3
11049--- /dev/null
11050+++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url-from-preload.tentative.html
11051@@ -0,0 +1,47 @@
11052+<!DOCTYPE html>
11053+<title>CSS integration - child CSS fetch from inline stylesheet</title>
11054+<link rel="help" href="https://crbug.com/1158645" />
11055+
11056+<head>
11057+  <meta name="referrer" content="origin">
11058+</head>
11059+
11060+<body>
11061+
11062+  <script src="/resources/testharness.js"></script>
11063+  <script src="/resources/testharnessreport.js"></script>
11064+  <script src="/common/utils.js"></script>
11065+  <!-- Common global functions for referrer-policy tests. -->
11066+  <script src="/common/security-features/resources/common.sub.js"></script>
11067+
11068+  <script>
11069+    promise_test(function (css_test) {
11070+        let id = token();
11071+        let url_prefix = location.protocol + "//www." + location.hostname +
11072+          ":" + location.port;
11073+        let css_url = url_prefix +
11074+          "/common/security-features/subresource/stylesheet.py?id=" + id +
11075+          "&type=stylesheet-only";
11076+        let check_url = url_prefix +
11077+          "/common/security-features/subresource/stylesheet.py" +
11078+          "?id=" + id + "&report-headers";
11079+
11080+        const frame = document.createElement('iframe');
11081+        const contents = `
11082+              <base href="http://other-site.example" />
11083+              <style type=text/css>
11084+                @import url('${css_url}');
11085+              </style>`;
11086+        frame.srcdoc = contents;
11087+        document.body.appendChild(frame);
11088+        return timeoutPromise(css_test, 1000)
11089+          .then(() => requestViaXhr(check_url))
11090+          .then(function (message) {
11091+            assert_own_property(message, "headers");
11092+            assert_own_property(message, "referrer");
11093+            assert_equals(message.referrer, location.origin + "/");
11094+          });
11095+      }, "A child stylesheet from inline style should use the document's" +
11096+      " URL, not the document's base URL, as its referrer, even when the " +
11097+      "HTML parser preloads the stylesheet.");
11098+  </script>
11099diff --git a/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url.tentative.html b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url.tentative.html
11100new file mode 100644
11101index 0000000000..7130e2a14a
11102--- /dev/null
11103+++ b/third_party/blink/web_tests/external/wpt/referrer-policy/css-integration/child-css/internal-import-stylesheet-with-differentorigin-base-url.tentative.html
11104@@ -0,0 +1,47 @@
11105+<!DOCTYPE html>
11106+<title>CSS integration - Child css from internal stylesheet</title>
11107+<link rel="help" href="https://crbug.com/1158645" />
11108+
11109+<head>
11110+  <meta name="referrer" content="origin">
11111+</head>
11112+
11113+<script src="/resources/testharness.js"></script>
11114+<script src="/resources/testharnessreport.js"></script>
11115+<script src="/common/utils.js"></script>
11116+<!-- Common global functions for referrer-policy tests. -->
11117+<script src="/common/security-features/resources/common.sub.js"></script>
11118+
11119+<!-- This has to follow the <script> tags, or it will make the .js files
11120+fail to load. -->
11121+<base href="http://other-site.example" />
11122+
11123+<script>
11124+  promise_test(function (css_test) {
11125+      let id = token();
11126+      let url_prefix = location.protocol + "//www1." + location.hostname +
11127+        ":" + location.port;
11128+      let css_url = url_prefix +
11129+        "/common/security-features/subresource/stylesheet.py?id=" + id +
11130+        "&stylesheet-only";
11131+      let check_url = url_prefix +
11132+        "/common/security-features/subresource/stylesheet.py" +
11133+        "?id=" + id + "&report-headers";
11134+
11135+      let style = document.createElement("style");
11136+      style.type = 'text/css';
11137+      style.appendChild(document.createTextNode("@import url('" + css_url +
11138+        "');"));
11139+      document.head.appendChild(style);
11140+      return timeoutPromise(css_test, 1000)
11141+        .then(() => requestViaXhr(check_url))
11142+        .then(function (message) {
11143+          assert_own_property(message, "headers");
11144+          assert_own_property(message, "referrer");
11145+          assert_equals(message.referrer, location.origin + "/");
11146+        });
11147+    },
11148+    "A child stylesheet from inline style should use the document's URL, not " +
11149+    "the document's base URL, as its referrer."
11150+  );
11151+</script>
11152diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
11153index b45910a3b8..f60c4b905e 100644
11154--- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
11155+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
11156@@ -144,7 +144,14 @@ cache_test(function(cache, test) {
11157               'Test framework error: The status code should be 0 for an ' +
11158               ' opaque-filtered response. This is actually HTTP 206.');
11159           response = fetch_result.clone();
11160-          return promise_rejects_js(test, TypeError, cache.put(request, fetch_result));
11161+          return cache.put(request, fetch_result);
11162+        })
11163+      .then(function() {
11164+          return cache.match(test_url);
11165+        })
11166+      .then(function(result) {
11167+          assert_not_equals(result, undefined,
11168+              'Cache.put should store an entry for the opaque response');
11169         });
11170   }, 'Cache.put with opaque-filtered HTTP 206 response');
11171
11172diff --git a/third_party/blink/web_tests/fast/peerconnection/poc-123067.html b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
11173new file mode 100644
11174index 0000000000..ff169f1d1e
11175--- /dev/null
11176+++ b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
11177@@ -0,0 +1,71 @@
11178+<!DOCTYPE html>
11179+<html>
11180+
11181+  <head>
11182+    <script src="../../resources/testharness.js"></script>
11183+    <script src="../../resources/testharnessreport.js"></script>
11184+    <script src="../../resources/gc.js"></script>
11185+  </head>
11186+  <body>
11187+  <script>
11188+    'use strict';
11189+  promise_test(async t => {
11190+    const var_caller_1 = new RTCPeerConnection();
11191+    const var_callee_1 = new RTCPeerConnection();
11192+    var_caller_1.addTransceiver('audio');
11193+    const var_prom_1 = new Promise(resolve => {
11194+      var_caller_1.onicecandidate = e => resolve(e.candidate);
11195+    });
11196+    await var_caller_1.setLocalDescription(await var_caller_1.createOffer());
11197+    await var_callee_1.setRemoteDescription(var_caller_1.localDescription);
11198+    const candidate = await var_prom_1;
11199+    var arrProm = [];
11200+    gc();
11201+    var_callee_1.setLocalDescription().then(() => {
11202+    })
11203+    var_callee_1.setLocalDescription().then(() => {
11204+    })
11205+    var_callee_1.setLocalDescription().then(() => {
11206+    })
11207+    var_callee_1.setLocalDescription().then(() => {
11208+    })
11209+    var_callee_1.setLocalDescription().then(() => {
11210+    })
11211+    var_callee_1.setLocalDescription().then(() => {
11212+    })
11213+    var_callee_1.setLocalDescription().then(() => {
11214+    })
11215+    var_callee_1.setLocalDescription().then(() => {
11216+    })
11217+    var_callee_1.setLocalDescription().then(() => {
11218+    })
11219+    var_callee_1.setLocalDescription().then(() => {
11220+    })
11221+    var_callee_1.setLocalDescription().then(() => {
11222+    })
11223+    var_callee_1.setLocalDescription().then(() => {
11224+    })
11225+    var_callee_1.setLocalDescription().then(() => {
11226+    })
11227+    var_callee_1.setLocalDescription().then(() => {
11228+    })
11229+    var_callee_1.setLocalDescription().then(() => {
11230+    })
11231+    var_callee_1.setLocalDescription().then(() => {
11232+    })
11233+    var_callee_1.setLocalDescription().then(() => {
11234+    })
11235+    var_callee_1.setLocalDescription().then(() => {
11236+    })
11237+    var_callee_1.setLocalDescription().then(() => {
11238+    })
11239+    var_callee_1.addIceCandidate(candidate).then(() => {
11240+    })
11241+    await Promise.all(arrProm);
11242+  }, 'Running this script does not cause an UAF');
11243+  </script>
11244+</head>
11245+
11246+<body></body>
11247+
11248+</html>
11249diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
11250new file mode 100644
11251index 0000000000..fbbc26b08e
11252--- /dev/null
11253+++ b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
11254@@ -0,0 +1,57 @@
11255+<!DOCTYPE html>
11256+<meta charset="utf-8">
11257+<script src="/resources/testharness.js"></script>
11258+<script src="/resources/testharnessreport.js"></script>
11259+<script>
11260+'use strict';
11261+
11262+test(t => {
11263+  Object.defineProperty(Object.prototype, 'type',
11264+                        {
11265+                          configurable: true,
11266+                          get() {
11267+                            throw Error();
11268+                          }
11269+                        });
11270+  t.add_cleanup(() => {
11271+    delete Object.prototype.type;
11272+  });
11273+  const generator = new MediaStreamTrackGenerator('video');
11274+  // The WritableStream is created lazily, so access it to trigger creation.
11275+  generator.writable.getWriter();
11276+}, 'a throwing getter on Object.prototype.type should not interfere with ' +
11277+     'native writable stream creation');
11278+
11279+test(t => {
11280+  Object.defineProperty(Object.prototype, 'type',
11281+                        {
11282+                          configurable: true,
11283+                          get() {
11284+                            this.start(0x414141);
11285+                          }
11286+                        });
11287+  t.add_cleanup(() => {
11288+    delete Object.prototype.type;
11289+  });
11290+  const generator = new MediaStreamTrackGenerator('video');
11291+  generator.writable.getWriter();
11292+}, 'a getter that calls start() with a number on Object.prototype.type ' +
11293+     'should not interfere with native writable stream creation');
11294+
11295+test(t => {
11296+  Object.defineProperty(Object.prototype, 'type',
11297+                        {
11298+                          configurable: true,
11299+                          get() {
11300+                            this.start({});
11301+                          }
11302+                        });
11303+  t.add_cleanup(() => {
11304+    delete Object.prototype.type;
11305+  });
11306+  const generator = new MediaStreamTrackGenerator('video');
11307+  generator.writable.getWriter();
11308+}, 'a getter that calls start() with an object on Object.prototype.type ' +
11309+     'should not interfere with native writable stream creation');
11310+
11311+</script>
11312diff --git a/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
11313new file mode 100644
11314index 0000000000..85397c5cc6
11315--- /dev/null
11316+++ b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
11317@@ -0,0 +1,39 @@
11318+<!DOCTYPE html>
11319+<html>
11320+<head>
11321+  <title>
11322+    Test if a corner case crashes the exponential ramp.
11323+  </title>
11324+  <script src="../../resources/testharness.js"></script>
11325+  <script src="../../resources/testharnessreport.js"></script>
11326+</head>
11327+<body>
11328+  <script>
11329+    const t = async_test('exponential-ramp-crash');
11330+
11331+    const onload = () => {
11332+      const context = new OfflineAudioContext(2, 441000, 44100);
11333+      const source = new ConstantSourceNode(context);
11334+      const delay_node = context.createDelay(30);
11335+      delay_node.connect(context.destination);
11336+      // The time overlap between 4.1s and 4s caused a crash in M95:
11337+      // https://crbug.com/1253746
11338+      delay_node.delayTime.exponentialRampToValueAtTime(2, 4.1);
11339+      delay_node.delayTime.cancelAndHoldAtTime(4);
11340+      context.oncomplete = t.step_func_done(() => {
11341+        // The |delay_node.delayTime| value should be zero because it does not
11342+        // have the previous anchor value. Based on the specification, if the
11343+        // beginning of an expoential ramp is zero, the resulting value falls
11344+        // into zero. In this case, there was no value point before the
11345+        // exponential ramp, and having no value point is treated as a
11346+        // default value, which is zero for |delayTime|.
11347+        assert_equals(delay_node.delayTime.value, 0);
11348+        assert_equals(context.state, 'closed');
11349+      });
11350+      context.startRendering();
11351+    };
11352+
11353+    window.addEventListener('load', t.step_func(onload));
11354+  </script>
11355+</body>
11356+</html>
11357diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
11358index e6f55d6ca1..808a241114 100644
11359--- a/tools/metrics/histograms/enums.xml
11360+++ b/tools/metrics/histograms/enums.xml
11361@@ -7143,6 +7143,7 @@ Called by update_bad_message_reasons.py.-->
11362   <int value="240" label="WCI_INVALID_FULLSCREEN_OPTIONS"/>
11363   <int value="241" label="PAYMENTS_WITHOUT_PERMISSION"/>
11364   <int value="242" label="WEB_BUNDLE_INVALID_NAVIGATION_URL"/>
11365+  <int value="254" label="RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS"/>
11366 </enum>
11367
11368 <enum name="BadMessageReasonExtensions">
11369diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
11370index 1032f1e903..3f0110f0ee 100644
11371--- a/ui/base/resource/resource_bundle.cc
11372+++ b/ui/base/resource/resource_bundle.cc
11373@@ -379,7 +379,7 @@ base::FilePath ResourceBundle::GetLocaleFilePath(
11374 #else
11375   if (base::PathService::Get(base::DIR_ASSETS, &locale_file_path)) {
11376     locale_file_path =
11377-        locale_file_path.AppendASCII(app_locale + kPakFileExtension);
11378+        locale_file_path.AppendASCII(std::string("locales/") + app_locale + kPakFileExtension);
11379   }
11380 #endif
11381
11382diff --git a/ui/ozone/common/BUILD.gn b/ui/ozone/common/BUILD.gn
11383index 59c8b17465..267f0c37ba 100644
11384--- a/ui/ozone/common/BUILD.gn
11385+++ b/ui/ozone/common/BUILD.gn
11386@@ -4,6 +4,7 @@
11387
11388 import("//build/config/ozone.gni")
11389 import("//build/config/ui.gni")
11390+import("//build/config/ohos/config.gni")
11391
11392 assert(use_ozone)
11393
11394@@ -26,6 +27,10 @@ source_set("common") {
11395     "//ui/ozone:ozone_base",
11396   ]
11397
11398+  if (product_name == "rk3568") {
11399+    defines = [ "GL_RK3568" ]
11400+  }
11401+
11402   deps = [
11403     "//ui/gfx/ipc/color",
11404     "//ui/gl",
11405diff --git a/ui/ozone/common/egl_util.cc b/ui/ozone/common/egl_util.cc
11406index 7eda22ffbb..5c5a416cfc 100644
11407--- a/ui/ozone/common/egl_util.cc
11408+++ b/ui/ozone/common/egl_util.cc
11409@@ -37,8 +37,13 @@ const base::FilePath::CharType kDefaultGlesSoname[] =
11410 #elif defined(OS_OHOS)
11411 const base::FilePath::CharType kDefaultEglSoname[] =
11412     FILE_PATH_LITERAL("libEGL.so");
11413+#if defined(GL_RK3568)
11414+const base::FilePath::CharType kDefaultGlesSoname[] =
11415+    FILE_PATH_LITERAL("libGLESv2.so");
11416+#else
11417 const base::FilePath::CharType kDefaultGlesSoname[] =
11418     FILE_PATH_LITERAL("libGLES_mali.so");
11419+#endif
11420 #else
11421 const base::FilePath::CharType kDefaultEglSoname[] =
11422     FILE_PATH_LITERAL("libEGL.so.1");
11423diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc
11424index 09dd241428..9aac59bc08 100644
11425--- a/ui/views/bubble/bubble_dialog_model_host.cc
11426+++ b/ui/views/bubble/bubble_dialog_model_host.cc
11427@@ -56,9 +56,8 @@ class CheckboxControl : public Checkbox {
11428       : label_line_height_(label_line_height) {
11429     auto* layout = SetLayoutManager(std::make_unique<BoxLayout>());
11430     layout->set_between_child_spacing(LayoutProvider::Get()->GetDistanceMetric(
11431-        views::DISTANCE_RELATED_LABEL_HORIZONTAL));
11432-    layout->set_cross_axis_alignment(
11433-        views::BoxLayout::CrossAxisAlignment::kStart);
11434+        DISTANCE_RELATED_LABEL_HORIZONTAL));
11435+    layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
11436
11437     SetAssociatedLabel(label.get());
11438
11439@@ -254,8 +253,8 @@ BubbleDialogModelHost::BubbleDialogModelHost(
11440   set_close_on_deactivate(model_->close_on_deactivate(GetPassKey()));
11441
11442   set_fixed_width(LayoutProvider::Get()->GetDistanceMetric(
11443-      anchor_view ? views::DISTANCE_BUBBLE_PREFERRED_WIDTH
11444-                  : views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
11445+      anchor_view ? DISTANCE_BUBBLE_PREFERRED_WIDTH
11446+                  : DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH));
11447
11448   AddInitialFields();
11449 }
11450@@ -464,17 +463,19 @@ void BubbleDialogModelHost::AddOrUpdateCombobox(
11451   combobox->SetCallback(base::BindRepeating(
11452       [](ui::DialogModelCombobox* model_field,
11453          base::PassKey<DialogModelHost> pass_key, Combobox* combobox) {
11454-        // TODO(pbos): This should be a subscription through the Combobox
11455-        // directly, but Combobox right now doesn't support listening to
11456-        // selected-index changes.
11457-        model_field->OnSelectedIndexChanged(pass_key,
11458-                                            combobox->GetSelectedIndex());
11459         model_field->OnPerformAction(pass_key);
11460       },
11461       model_field, GetPassKey(), combobox.get()));
11462
11463-  // TODO(pbos): Add subscription to combobox selected-index changes.
11464   combobox->SetSelectedIndex(model_field->selected_index());
11465+  property_changed_subscriptions_.push_back(
11466+      combobox->AddSelectedIndexChangedCallback(base::BindRepeating(
11467+          [](ui::DialogModelCombobox* model_field,
11468+             base::PassKey<DialogModelHost> pass_key, Combobox* combobox) {
11469+            model_field->OnSelectedIndexChanged(pass_key,
11470+                                                combobox->GetSelectedIndex());
11471+          },
11472+          model_field, GetPassKey(), combobox.get())));
11473   const gfx::FontList& font_list = combobox->GetFontList();
11474   AddViewForLabelAndField(model_field, model_field->label(GetPassKey()),
11475                           std::move(combobox), font_list);
11476diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc
11477index 8fd0088e02..c25a7c5e57 100644
11478--- a/ui/views/controls/combobox/combobox.cc
11479+++ b/ui/views/controls/combobox/combobox.cc
11480@@ -281,6 +281,7 @@ const gfx::FontList& Combobox::GetFontList() const {
11481 void Combobox::SetSelectedIndex(int index) {
11482   if (selected_index_ == index)
11483     return;
11484+  // TODO(pbos): Add (D)CHECKs to validate the selected index.
11485   selected_index_ = index;
11486   if (size_to_largest_label_) {
11487     OnPropertyChanged(&selected_index_, kPropertyEffectsPaint);
11488@@ -290,6 +291,11 @@ void Combobox::SetSelectedIndex(int index) {
11489   }
11490 }
11491
11492+base::CallbackListSubscription Combobox::AddSelectedIndexChangedCallback(
11493+    views::PropertyChangedCallback callback) {
11494+  return AddPropertyChangedCallback(&selected_index_, std::move(callback));
11495+}
11496+
11497 bool Combobox::SelectValue(const std::u16string& value) {
11498   for (int i = 0; i < GetModel()->GetItemCount(); ++i) {
11499     if (value == GetModel()->GetItemAt(i)) {
11500@@ -430,9 +436,11 @@ bool Combobox::OnKeyPressed(const ui::KeyEvent& e) {
11501   // TODO(oshima): handle IME.
11502   DCHECK_EQ(e.type(), ui::ET_KEY_PRESSED);
11503
11504+  // TODO(pbos): Do we need to handle selected_index_ == -1 for unselected here?
11505+  // Ditto on handling an empty model?
11506   DCHECK_GE(selected_index_, 0);
11507   DCHECK_LT(selected_index_, GetModel()->GetItemCount());
11508-  if (selected_index_ < 0 || selected_index_ > GetModel()->GetItemCount())
11509+  if (selected_index_ < 0 || selected_index_ >= GetModel()->GetItemCount())
11510     SetSelectedIndex(0);
11511
11512   bool show_menu = false;
11513@@ -618,10 +626,13 @@ void Combobox::PaintIconAndText(gfx::Canvas* canvas) {
11514
11515   // Draw the text.
11516   SkColor text_color = GetTextColorForEnableState(*this, GetEnabled());
11517-  if (selected_index_ < 0 || selected_index_ > GetModel()->GetItemCount()) {
11518-    NOTREACHED();
11519+  // TODO(pbos): Do we need to handle selected_index_ == -1 for unselected here?
11520+  // Ditto on handling an empty model?
11521+  DCHECK_GE(selected_index_, 0);
11522+  DCHECK_LT(selected_index_, GetModel()->GetItemCount());
11523+  if (selected_index_ < 0 || selected_index_ >= GetModel()->GetItemCount())
11524     SetSelectedIndex(0);
11525-  }
11526+
11527   std::u16string text = GetModel()->GetItemAt(selected_index_);
11528
11529   int disclosure_arrow_offset = width() - kComboboxArrowContainerWidth;
11530diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h
11531index 303b9e5d9a..2dccca063e 100644
11532--- a/ui/views/controls/combobox/combobox.h
11533+++ b/ui/views/controls/combobox/combobox.h
11534@@ -71,6 +71,8 @@ class VIEWS_EXPORT Combobox : public View,
11535   // Gets/Sets the selected index.
11536   int GetSelectedIndex() const { return selected_index_; }
11537   void SetSelectedIndex(int index);
11538+  base::CallbackListSubscription AddSelectedIndexChangedCallback(
11539+      views::PropertyChangedCallback callback) WARN_UNUSED_RESULT;
11540
11541   // Looks for the first occurrence of |value| in |model()|. If found, selects
11542   // the found index and returns true. Otherwise simply noops and returns false.
11543