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+ ®istration_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