diff --git a/DEPS b/DEPS index 22cd18ec..6478d08 100644 --- a/DEPS +++ b/DEPS
@@ -298,11 +298,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '68a0212d298bc788debdbb225a168be96f63c7dd', + 'v8_revision': '5110982b4020c8303ab7aece58818cb7eaee972e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'b89c600819486f7187ac958b6396eafa2b1bd1ac', + 'angle_revision': 'cb432540e120916a9f503be74d128be74ec2ae8e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -314,7 +314,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': '860c27038fcd9c2c27242e9874c18408dec1f84c', + 'boringssl_revision': 'f51d8b099832f805022a6ff2e9466dbcacdfb0ab', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. @@ -358,7 +358,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '116ec83ba82d63aeb64fc56a4b0912947492f1df', + 'catapult_revision': 'a03b70978cc52840b549947f0fb165f03764c700', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -370,7 +370,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling fuzztest # and whatever else without interference from each other. - 'fuzztest_revision': '6c64b55603eab828e5acb92d40cf92c663194fb2', + 'fuzztest_revision': '45a1c3ad5ac3de58c8e9a3f89036e3f954820d4c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling domato # and whatever else without interference from each other. @@ -378,7 +378,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': 'f5f6ac59025c9c34c1626573d6b5f77f804509ba', + 'devtools_frontend_revision': 'b0196172485ea5c6606d909d19a4e066ee32c004', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -402,7 +402,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '3f5a9376dea63b041f604afef820651213272a9d', + 'dawn_revision': '5602ae03628ac1ae4ba8d265ac1979abea42d6ba', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1563,7 +1563,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '02d6754dd5cd180b7288bcbaed9b9e0a8a66b395', + '87688db09fa1af75f935e82e11b7e21594f2c443', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1572,7 +1572,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '4d03903575101220da2ab2262376d2b1b9a14dc4', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '26e72194d8863202aeaad2f124f7964ae3f3934f', 'condition': 'checkout_ios', }, @@ -2330,7 +2330,7 @@ Var('chromium_git') + '/external/libaddressinput.git' + '@' + '2610f7b1043d6784ada41392fc9392d1ea09ea07', 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '6c4010bde34318fd6c1f0d10196f27ac9908eeb8', + Var('aomedia_git') + '/aom.git' + '@' + '0ddc6630b3723b14b164752d46c27752f078ddd3', 'src/third_party/crabbyavif/src': Var('chromium_git') + '/external/github.com/webmproject/CrabbyAvif.git' + '@' + Var('crabbyavif_revision'), @@ -2593,7 +2593,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '9d9c4e778b7867127e336d7560ddb49525b12faf', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '21d660f5550822d7bcf79c43595ffbf258fe681a', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2912,11 +2912,11 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@0dbbf0da762246640feffd8182cf1276c20ee898', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@565c281d73214e4712bd78be4cb7ccc2833ea471', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@21b4e37133868b3a50ef15fc027ecd6d3a52c875', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@2a611a970fdbc41ac2e3e328802aed9985352dca', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@c837be3e42a61a69a07c959ffc95871bf5a16525', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@85607567adde930f1598024116caa1ff9831848c', 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@10739e8e00a7b6f74d22dd0a547f1406ff1f5eb9', 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@dc6786e527cf8cefd244318f546b3b2ec26e84f4', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@d671923090e4dc74c0ebdb10c6e09fa0826e1fe9', @@ -3099,7 +3099,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'm10SwGuuVH0QFwZe_Lc87HLp_-6nS0sUMUa-P7wuElMC', + 'version': 'X0OvKJ4hTgwGhoHFfwpOP6nzXL0HNoNKioTe7Tq4CykC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4496,7 +4496,7 @@ 'src/chrome/browser/glic/resources/internal': { 'url': Var('chrome_git') + '/chrome/browser/glic/resources/internal.git' + '@' + - '475441278dca99489f0e148f278ca395fd07926d', + 'c423a1559c0be8f0c1748dcdb0971ce13bf5dbcd', 'condition': 'checkout_src_internal', }, @@ -4686,7 +4686,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - 'dcfc4528bdad156f1743629801618682fd9f7785', + '9e8ee5114eb95c9675a3ea819e20773bc26e760c', 'condition': 'checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 2c7056f..7d2f767 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2530,7 +2530,6 @@ 'ai_page_content': ['mfoltz+watch@chromium.org'], 'ai_settings_page_desktop': ['rainhard+watch@chromium.org'], 'android_accessibility': ['mschillaci+watcha11y@google.com', - 'zhangwenyu+watcha11y@google.com', 'cambickel+watcha11y@google.com', 'michaelcheco+watcha11y@google.com', 'jhawkins+watcha11y@google.com'],
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index eaf39f77..23c6edbe 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -533,8 +533,6 @@ "java/src/org/chromium/android_webview/contextmenu/AwContextMenuItemViewBinder.java", "java/src/org/chromium/android_webview/contextmenu/AwContextMenuPopulator.java", "java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java", - "java/src/org/chromium/android_webview/gfx/AwFunctor.java", - "java/src/org/chromium/android_webview/gfx/AwGLFunctor.java", "java/src/org/chromium/android_webview/gfx/AwPicture.java", "java/src/org/chromium/android_webview/gfx/JavaBrowserViewRendererHelper.java", "java/src/org/chromium/android_webview/gfx/RectUtils.java", @@ -686,13 +684,14 @@ "java/src/org/chromium/android_webview/common/MediaIntegrityErrorWrapper.java", "java/src/org/chromium/android_webview/common/MediaIntegrityNonRecoverableErrorLogger.java", "java/src/org/chromium/android_webview/common/MediaIntegrityProvider.java", + "java/src/org/chromium/android_webview/common/NoOpPlatformServiceBridge.java", "java/src/org/chromium/android_webview/common/PlatformServiceBridge.java", - "java/src/org/chromium/android_webview/common/PlatformServiceBridgeImpl.java", "java/src/org/chromium/android_webview/common/ValueOrErrorCallback.java", ] deps = [ "//base:base_java", + "//base:service_loader_java", "//components/embedder_support/android/metrics:java", "//content/public/android:content_full_java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -702,13 +701,6 @@ # The appropriate .class file will be loaded via a dependency to a library # like :platform_service_bridge_upstream_implementation_java below. We only include the # .java file because other files in the target depend on it. - jar_excluded_patterns = [ "*/PlatformServiceBridgeImpl.class" ] - } - - # This target compiles the implementation of PlatformServiceBridge for AOSP targets. - android_library("platform_service_bridge_upstream_implementation_java") { - sources = [ "java/src/org/chromium/android_webview/common/PlatformServiceBridgeImpl.java" ] - deps = [ ":common_platform_services_java" ] } android_library("crash_client_java") { @@ -1201,7 +1193,6 @@ "java/src/org/chromium/android_webview/client_hints/AwUserAgentMetadata.java", "java/src/org/chromium/android_webview/contextmenu/AwContextMenuHelper.java", "java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java", - "java/src/org/chromium/android_webview/gfx/AwGLFunctor.java", "java/src/org/chromium/android_webview/gfx/AwPicture.java", "java/src/org/chromium/android_webview/gfx/JavaBrowserViewRendererHelper.java", "java/src/org/chromium/android_webview/gfx/RootBeginFrameSourceWebView.java",
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc index f8c82d1..4b32a64 100644 --- a/android_webview/browser/aw_contents.cc +++ b/android_webview/browser/aw_contents.cc
@@ -21,7 +21,6 @@ #include "android_webview/browser/aw_renderer_priority.h" #include "android_webview/browser/aw_settings.h" #include "android_webview/browser/aw_web_contents_delegate.h" -#include "android_webview/browser/gfx/aw_gl_functor.h" #include "android_webview/browser/gfx/aw_picture.h" #include "android_webview/browser/gfx/browser_view_renderer.h" #include "android_webview/browser/gfx/child_frame.h" @@ -491,9 +490,6 @@ reinterpret_cast<AwDrawSWFunctionTable*>(function_table)); } -static void JNI_AwContents_SetAwDrawGLFunctionTable(JNIEnv* env, - jlong function_table) {} - // static jint JNI_AwContents_GetNativeInstanceCount(JNIEnv* env) { return base::subtle::NoBarrier_Load(&g_instance_count);
diff --git a/android_webview/browser/gfx/BUILD.gn b/android_webview/browser/gfx/BUILD.gn index 5b2857e..0177d54c 100644 --- a/android_webview/browser/gfx/BUILD.gn +++ b/android_webview/browser/gfx/BUILD.gn
@@ -9,8 +9,6 @@ sources = [ "aw_draw_fn_impl.cc", "aw_draw_fn_impl.h", - "aw_gl_functor.cc", - "aw_gl_functor.h", "aw_gl_surface.cc", "aw_gl_surface.h", "aw_gl_surface_external_stencil.cc",
diff --git a/android_webview/browser/gfx/aw_draw_fn_impl.cc b/android_webview/browser/gfx/aw_draw_fn_impl.cc index 1b68c019..64627dec 100644 --- a/android_webview/browser/gfx/aw_draw_fn_impl.cc +++ b/android_webview/browser/gfx/aw_draw_fn_impl.cc
@@ -32,6 +32,8 @@ namespace { +int g_instance_count = 0; + // Set once during process-wide initialization. AwDrawFnFunctionTable* g_draw_fn_function_table = nullptr; @@ -211,6 +213,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(g_draw_fn_function_table); + ++g_instance_count; + static AwDrawFnFunctorCallbacks g_functor_callbacks{ &OnSyncWrapper, &OnContextDestroyedWrapper, &OnDestroyedWrapper, &DrawGLWrapper, @@ -226,11 +230,13 @@ } } -AwDrawFnImpl::~AwDrawFnImpl() {} +AwDrawFnImpl::~AwDrawFnImpl() = default; void AwDrawFnImpl::ReleaseHandle( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + --g_instance_count; render_thread_manager_.RemoveFromCompositorFrameProducerOnUI(); g_draw_fn_function_table->release_functor(functor_handle_); } @@ -348,4 +354,9 @@ render_thread_manager_.RemoveOverlaysOnRT(params->merge_transaction); } +static jint JNI_AwDrawFnImpl_GetReferenceInstanceCount(JNIEnv* env) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return g_instance_count; +} + } // namespace android_webview
diff --git a/android_webview/browser/gfx/aw_gl_functor.cc b/android_webview/browser/gfx/aw_gl_functor.cc deleted file mode 100644 index 9627e7f..0000000 --- a/android_webview/browser/gfx/aw_gl_functor.cc +++ /dev/null
@@ -1,165 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - -#include "android_webview/browser/gfx/aw_gl_functor.h" - -#include "android_webview/public/browser/draw_gl.h" -#include "base/trace_event/trace_event.h" -#include "content/public/browser/browser_task_traits.h" -#include "content/public/browser/browser_thread.h" - -// Must come after all headers that specialize FromJniType() / ToJniType(). -#include "android_webview/browser_jni_headers/AwGLFunctor_jni.h" - -using base::android::JavaParamRef; -using base::android::ScopedJavaLocalRef; -using content::BrowserThread; -using jni_zero::AttachCurrentThread; - -extern "C" { -static AwDrawGLFunction DrawGLFunction; -static void DrawGLFunction(long view_context, - AwDrawGLInfo* draw_info, - void* spare) { - // |view_context| is the value that was returned from the java - // AwContents.onPrepareDrawGL; this cast must match the code there. - reinterpret_cast<android_webview::AwGLFunctor*>(view_context) - ->DrawGL(draw_info); -} -} - -namespace android_webview { - -namespace { -int g_instance_count = 0; -} - -AwGLFunctor::AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref) - : java_ref_(java_ref), - render_thread_manager_(content::GetUIThreadTaskRunner({})) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - ++g_instance_count; -} - -AwGLFunctor::~AwGLFunctor() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - --g_instance_count; -} - -bool AwGLFunctor::RequestInvokeGL(bool wait_for_completion) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (!obj) - return false; - return Java_AwGLFunctor_requestInvokeGL(env, obj, wait_for_completion); -} - -void AwGLFunctor::DetachFunctorFromView() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (obj) - Java_AwGLFunctor_detachFunctorFromView(env, obj); -} - -void AwGLFunctor::Destroy(JNIEnv* env) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - java_ref_.reset(); - delete this; -} - -void AwGLFunctor::DeleteHardwareRenderer( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - RenderThreadManager::InsideHardwareReleaseReset release_reset( - &render_thread_manager_); - DetachFunctorFromView(); - - // Receiving at least one frame is a precondition for - // initialization (such as looing up GL bindings and constructing - // hardware_renderer_). - bool draw_functor_succeeded = RequestInvokeGL(true); - if (!draw_functor_succeeded) { - LOG(ERROR) << "Unable to free GL resources. Has the Window leaked?"; - // Calling release on wrong thread intentionally. - render_thread_manager_.DestroyHardwareRendererOnRT( - true /* save_restore */, false /* abandon_context */); - } -} - -void AwGLFunctor::DrawGL(AwDrawGLInfo* draw_info) { - TRACE_EVENT0("android_webview,toplevel", "DrawFunctor"); - bool save_restore = draw_info->version < 3; - switch (draw_info->mode) { - case AwDrawGLInfo::kModeSync: - TRACE_EVENT_INSTANT0("android_webview", "kModeSync", - TRACE_EVENT_SCOPE_THREAD); - render_thread_manager_.CommitFrameOnRT(); - break; - case AwDrawGLInfo::kModeProcessNoContext: - LOG(ERROR) << "Received unexpected kModeProcessNoContext"; - render_thread_manager_.DestroyHardwareRendererOnRT( - save_restore, true /* abandon_context */); - break; - case AwDrawGLInfo::kModeProcess: - render_thread_manager_.DestroyHardwareRendererOnRT( - save_restore, false /* abandon_context */); - break; - case AwDrawGLInfo::kModeDraw: { - HardwareRendererDrawParams params{ - draw_info->clip_left, draw_info->clip_top, draw_info->clip_right, - draw_info->clip_bottom, draw_info->width, draw_info->height, - }; - static_assert(std::size(decltype(draw_info->transform){}) == - std::size(params.transform), - "transform size mismatch"); - for (unsigned int i = 0; i < std::size(params.transform); ++i) { - params.transform[i] = draw_info->transform[i]; - } - render_thread_manager_.DrawOnRT(save_restore, params, OverlaysParams(), - ReportRenderingThreadsCallback()); - break; - } - } -} - -void AwGLFunctor::RemoveFromCompositorFrameProducer( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - render_thread_manager_.RemoveFromCompositorFrameProducerOnUI(); -} - -jlong AwGLFunctor::GetCompositorFrameConsumer( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - return reinterpret_cast<intptr_t>(GetCompositorFrameConsumer()); -} - -static jint JNI_AwGLFunctor_GetNativeInstanceCount(JNIEnv* env) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - return g_instance_count; -} - -static jlong JNI_AwGLFunctor_GetAwDrawGLFunction(JNIEnv* env) { - return reinterpret_cast<intptr_t>(&DrawGLFunction); -} - -static jlong JNI_AwGLFunctor_Create( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - return reinterpret_cast<intptr_t>( - new AwGLFunctor(JavaObjectWeakGlobalRef(env, obj))); -} - -} // namespace android_webview
diff --git a/android_webview/browser/gfx/aw_gl_functor.h b/android_webview/browser/gfx/aw_gl_functor.h deleted file mode 100644 index bc5eb35..0000000 --- a/android_webview/browser/gfx/aw_gl_functor.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_FUNCTOR_H_ -#define ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_FUNCTOR_H_ - -#include "android_webview/browser/gfx/compositor_frame_consumer.h" -#include "android_webview/browser/gfx/render_thread_manager.h" -#include "base/android/jni_weak_ref.h" - -struct AwDrawGLInfo; - -namespace android_webview { - -// Lifetime: WebView -class AwGLFunctor { - public: - explicit AwGLFunctor(const JavaObjectWeakGlobalRef& java_ref); - ~AwGLFunctor(); - - void Destroy(JNIEnv* env); - void DeleteHardwareRenderer(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - void RemoveFromCompositorFrameProducer( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - jlong GetCompositorFrameConsumer( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - jlong GetAwDrawGLFunction(JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); - - void DrawGL(AwDrawGLInfo* draw_info); - - private: - bool RequestInvokeGL(bool wait_for_completion); - void DetachFunctorFromView(); - CompositorFrameConsumer* GetCompositorFrameConsumer() { - return &render_thread_manager_; - } - - JavaObjectWeakGlobalRef java_ref_; - RenderThreadManager render_thread_manager_; -}; - -} // namespace android_webview - -#endif // ANDROID_WEBVIEW_BROWSER_GFX_AW_GL_FUNCTOR_H_
diff --git a/android_webview/browser/gfx/render_thread_manager.cc b/android_webview/browser/gfx/render_thread_manager.cc index 8a209ed..30de2e2 100644 --- a/android_webview/browser/gfx/render_thread_manager.cc +++ b/android_webview/browser/gfx/render_thread_manager.cc
@@ -14,7 +14,6 @@ #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h" #include "android_webview/browser/gfx/task_queue_webview.h" #include "android_webview/common/aw_features.h" -#include "android_webview/public/browser/draw_gl.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/memory/ptr_util.h"
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java b/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java index 331628e..af2c2f44 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/DrawGLFunctor.java
@@ -4,68 +4,10 @@ package com.android.webview.chromium; -import android.graphics.Canvas; -import android.view.View; -import android.webkit.WebViewDelegate; - -import org.chromium.android_webview.AwContents; import org.chromium.build.annotations.UsedByReflection; -/** - * Simple Java abstraction and wrapper for the native DrawGLFunctor flow. An instance of this class - * can be constructed, bound to a single view context (i.e. AwContents) and then drawn and detached - * from the view tree any number of times (using requestDrawGL and detach respectively). - */ -class DrawGLFunctor implements AwContents.NativeDrawGLFunctor { - // Pointer to native side instance - private final WebViewDelegate mWebViewDelegate; - private long mNativeDrawGLFunctor; - - public DrawGLFunctor(long viewContext, WebViewDelegate webViewDelegate) { - mNativeDrawGLFunctor = nativeCreateGLFunctor(viewContext); - mWebViewDelegate = webViewDelegate; - } - - @Override - public void detach(View containerView) { - if (mNativeDrawGLFunctor == 0) { - throw new RuntimeException("detach on already destroyed DrawGLFunctor"); - } - mWebViewDelegate.detachDrawGlFunctor(containerView, mNativeDrawGLFunctor); - } - - @Override - public boolean requestDrawGL(Canvas canvas, Runnable releasedCallback) { - if (mNativeDrawGLFunctor == 0) { - throw new RuntimeException("requestDrawGL on already destroyed DrawGLFunctor"); - } - assert canvas != null; - assert releasedCallback != null; - mWebViewDelegate.callDrawGlFunction(canvas, mNativeDrawGLFunctor, releasedCallback); - return true; - } - - @Override - public boolean requestInvokeGL(View containerView, boolean waitForCompletion) { - if (mNativeDrawGLFunctor == 0) { - throw new RuntimeException("requestInvokeGL on already destroyed DrawGLFunctor"); - } - mWebViewDelegate.invokeDrawGlFunctor( - containerView, mNativeDrawGLFunctor, waitForCompletion); - return true; - } - - @Override - public void destroy() { - assert mNativeDrawGLFunctor != 0; - nativeDestroyGLFunctor(mNativeDrawGLFunctor); - mNativeDrawGLFunctor = 0; - } - - public static void setChromiumAwDrawGLFunction(long functionPointer) { - nativeSetChromiumAwDrawGLFunction(functionPointer); - } - +// Remove once all supported Android versions no longer implements these native functions. +class DrawGLFunctor { // The Android framework performs manual JNI registration on these methods, so the method // signatures cannot change without updating the framework. We use @UsedByReflection, while not // technically true, as a way to preserve these methods and their names.
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/GraphicsUtils.java b/android_webview/glue/java/src/com/android/webview/chromium/GraphicsUtils.java index ae814a8..538c21fa 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/GraphicsUtils.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/GraphicsUtils.java
@@ -11,10 +11,6 @@ return nativeGetDrawSWFunctionTable(); } - public static long getDrawGLFunctionTable() { - return nativeGetDrawGLFunctionTable(); - } - // The Android framework performs manual JNI registration on these methods, so the method // signatures cannot change without updating the framework. We use @UsedByReflection, while not // technically true, as a way to preserve these methods and their names.
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java index a96b9cb..c61ad089 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java
@@ -69,7 +69,6 @@ import org.chromium.android_webview.ManifestMetadataUtil; import org.chromium.android_webview.R; import org.chromium.android_webview.common.Lifetime; -import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.renderer_priority.RendererPriority; import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; @@ -907,7 +906,7 @@ mWebView, mContext, new InternalAccessAdapter(), - new WebViewNativeDrawFunctorFactory(), + mFactory.getWebViewDelegate()::drawWebViewFunctor, mContentsClientAdapter, mWebSettings.getAwSettings(), new AwContents.DependencyFactory()); @@ -3585,22 +3584,6 @@ } } - // AwContents.NativeDrawFunctorFactory implementation ---------------------------------- - private class WebViewNativeDrawFunctorFactory implements AwContents.NativeDrawFunctorFactory { - @Override - public AwContents.NativeDrawGLFunctor createGLFunctor(long context) { - return new DrawGLFunctor(context, mFactory.getWebViewDelegate()); - } - - @Override - public AwDrawFnImpl.DrawFnAccess getDrawFnAccess() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - return mFactory.getWebViewDelegate()::drawWebViewFunctor; - } - return null; - } - } - // AwContents.InternalAccessDelegate implementation -------------------------------------- private class InternalAccessAdapter implements AwContents.InternalAccessDelegate { @Override
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java index a62ed4d..d00463c0 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/WebViewChromiumAwInit.java
@@ -810,12 +810,8 @@ private void initPlatSupportLibrary() { try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped("WebViewChromiumAwInit.initPlatSupportLibrary")) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - AwDrawFnImpl.setDrawFnFunctionTable(DrawFunctor.getDrawFnFunctionTable()); - } - DrawGLFunctor.setChromiumAwDrawGLFunction(AwContents.getAwDrawGLFunction()); + AwDrawFnImpl.setDrawFnFunctionTable(DrawFunctor.getDrawFnFunctionTable()); AwContents.setAwDrawSWFunctionTable(GraphicsUtils.getDrawSWFunctionTable()); - AwContents.setAwDrawGLFunctionTable(GraphicsUtils.getDrawGLFunctionTable()); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index f632f340f..23cbf8c 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -67,8 +67,6 @@ import org.chromium.android_webview.common.AwSwitches; import org.chromium.android_webview.common.Lifetime; import org.chromium.android_webview.gfx.AwDrawFnImpl; -import org.chromium.android_webview.gfx.AwFunctor; -import org.chromium.android_webview.gfx.AwGLFunctor; import org.chromium.android_webview.gfx.AwPicture; import org.chromium.android_webview.metrics.AwOriginVisitLogger; import org.chromium.android_webview.metrics.BackForwardCacheNotRestoredReason; @@ -290,11 +288,13 @@ } /** - * Interface that consumers of {@link AwContents} must implement to allow the proper - * dispatching of view methods through the containing view. + * Interface that consumers of {@link AwContents} must implement to allow the proper dispatching + * of view methods through the containing view. */ public interface InternalAccessDelegate extends ViewEventSink.InternalAccessDelegate { - /** @see View#overScrollBy(int, int, int, int, int, int, int, int, boolean); */ + /** + * @see View#overScrollBy(int, int, int, int, int, int, int, int, boolean); + */ void overScrollBy( int deltaX, int deltaY, @@ -306,73 +306,33 @@ int maxOverScrollY, boolean isTouchEvent); - /** @see View#scrollTo(int, int) */ + /** + * @see View#scrollTo(int, int) + */ void super_scrollTo(int scrollX, int scrollY); - /** @see View#setMeasuredDimension(int, int) */ + /** + * @see View#setMeasuredDimension(int, int) + */ void setMeasuredDimension(int measuredWidth, int measuredHeight); - /** @see View#getScrollBarStyle() */ + /** + * @see View#getScrollBarStyle() + */ int super_getScrollBarStyle(); - /** @see View#startActivityForResult(Intent, int) */ + /** + * @see View#startActivityForResult(Intent, int) + */ void super_startActivityForResult(Intent intent, int requestCode); - /** @see View#onConfigurationChanged(Configuration) */ + /** + * @see View#onConfigurationChanged(Configuration) + */ void super_onConfigurationChanged(Configuration newConfig); } /** - * Factory interface used for constructing functors that the Android framework uses for - * calling back into Chromium code to render the the contents of a Chromium frame into - * an Android view. - */ - public interface NativeDrawFunctorFactory { - /** Create a GL functor associated with native context |context|. */ - NativeDrawGLFunctor createGLFunctor(long context); - - /** - * Used for draw_fn functor. Only one of these methods need to return non-null. - * Prefer this over createGLFunctor. - */ - AwDrawFnImpl.DrawFnAccess getDrawFnAccess(); - } - - /** - * Interface that consumers of {@link AwContents} must implement to support - * native GL rendering. - */ - public interface NativeDrawGLFunctor { - /** - * Requests a callback on the native DrawGL method (see getAwDrawGLFunction). - * - * If called from within onDraw, |canvas| should be non-null and must be hardware - * accelerated. |releasedCallback| should be null if |canvas| is null. - * - * @return false indicates the GL draw request was not accepted, and the caller - * should fallback to the SW path. - */ - boolean requestDrawGL(Canvas canvas, Runnable releasedCallback); - - /** - * Requests a callback on the native DrawGL method (see getAwDrawGLFunction). - * - * |containerView| must be hardware accelerated. If |waitForCompletion| is true, this method - * will not return until functor has returned. - */ - boolean requestInvokeGL(View containerView, boolean waitForCompletion); - - /** Detaches the GLFunctor from the view tree. */ - void detach(View containerView); - - /** - * Destroy this functor instance and any native objects associated with it. No method is - * called after destroy. - */ - void destroy(); - } - - /** * Class to facilitate dependency injection. Subclasses by test code to provide mock versions of * certain AwContents dependencies. */ @@ -403,7 +363,7 @@ private long mNativeAwContents; private AwBrowserContext mBrowserContext; private ViewGroup mContainerView; - private AwFunctor mDrawFunctor; + private AwDrawFnImpl mDrawFunctor; private final Context mContext; private final int mAppTargetSdkVersion; private AwViewAndroidDelegate mViewAndroidDelegate; @@ -421,7 +381,7 @@ private final AwContentsIoThreadClient mIoThreadClient; private final InterceptNavigationDelegateImpl mInterceptNavigationDelegate; private InternalAccessDelegate mInternalAccessAdapter; - private final NativeDrawFunctorFactory mNativeDrawFunctorFactory; + private final AwDrawFnImpl.DrawFnAccess mDrawFnAccess; private final AwLayoutSizer mLayoutSizer; private final AwZoomControls mZoomControls; private final AwScrollOffsetManager mScrollOffsetManager; @@ -952,7 +912,7 @@ * @param containerView the view-hierarchy item this object will be bound to. * @param context the context to use, usually containerView.getContext(). * @param internalAccessAdapter to access private methods on containerView. - * @param nativeDrawFunctorFactory to access the functor provided by the WebView. + * @param drawFnAccess to access the draw functor provided by the WebView. * @param contentsClient will receive API callbacks from this WebView Contents. * @param awSettings AwSettings instance used to configure the AwContents. * <p>This constructor uses the default view sizing policy. @@ -962,7 +922,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings awSettings) { this( @@ -970,7 +930,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, awSettings, new DependencyFactory()); @@ -987,7 +947,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -1062,7 +1022,7 @@ mContext = context; mAppTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; mInternalAccessAdapter = internalAccessAdapter; - mNativeDrawFunctorFactory = nativeDrawFunctorFactory; + mDrawFnAccess = drawFnAccess; mContentsClient = contentsClient; mContentsClient .getCallbackHelper() @@ -1582,9 +1542,9 @@ } } - private void setFunctor(AwFunctor functor) { + private void setFunctor(AwDrawFnImpl functor) { if (mDrawFunctor == functor) return; - AwFunctor oldFunctor = mDrawFunctor; + AwDrawFnImpl oldFunctor = mDrawFunctor; mDrawFunctor = functor; updateNativeAwGLFunctor(); @@ -2049,14 +2009,6 @@ AwContentsJni.get().setAwDrawSWFunctionTable(functionTablePointer); } - public static void setAwDrawGLFunctionTable(long functionTablePointer) { - AwContentsJni.get().setAwDrawGLFunctionTable(functionTablePointer); - } - - public static long getAwDrawGLFunction() { - return AwGLFunctor.getAwDrawGLFunction(); - } - public static void setShouldDownloadFavicons() { AwContentsJni.get().setShouldDownloadFavicons(); } @@ -4202,7 +4154,6 @@ postDelayedTaskWithOverride( this::maybeRecordMemory, METRICS_COLLECTION_DELAY_MS); if (mDrawFunctor != null) { - mDrawFunctor.trimMemory(); setFunctor(null); } } @@ -4309,7 +4260,7 @@ } } - @SuppressLint("DrawAllocation") // For new AwFunctor. + @SuppressLint("DrawAllocation") // For new AwDrawFnImpl. private void onDrawInner(Canvas canvas) { if (isDestroyed(NO_WARN)) { TraceEvent.instant("EarlyOut_destroyed"); @@ -4325,15 +4276,7 @@ } if (canvas.isHardwareAccelerated() && mDrawFunctor == null) { - AwFunctor newFunctor; - AwDrawFnImpl.DrawFnAccess drawFnAccess = - mNativeDrawFunctorFactory.getDrawFnAccess(); - if (drawFnAccess != null) { - newFunctor = new AwDrawFnImpl(drawFnAccess); - } else { - newFunctor = new AwGLFunctor(mNativeDrawFunctorFactory, mContainerView); - } - setFunctor(newFunctor); + setFunctor(new AwDrawFnImpl(mDrawFnAccess)); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { @@ -4812,8 +4755,6 @@ void setAwDrawSWFunctionTable(long functionTablePointer); - void setAwDrawGLFunctionTable(long functionTablePointer); - int getNativeInstanceCount(); void setShouldDownloadFavicons();
diff --git a/android_webview/java/src/org/chromium/android_webview/common/NoOpPlatformServiceBridge.java b/android_webview/java/src/org/chromium/android_webview/common/NoOpPlatformServiceBridge.java new file mode 100644 index 0000000..1a10747 --- /dev/null +++ b/android_webview/java/src/org/chromium/android_webview/common/NoOpPlatformServiceBridge.java
@@ -0,0 +1,12 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview.common; + +/** + * The default implementation of {@link PlatformServiceBridge}. + * + * <p>This can be overridden by defining a service implementation for {@link PlatformServiceBridge}. + */ +public class NoOpPlatformServiceBridge extends PlatformServiceBridge {}
diff --git a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java b/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java index 6400be79..77a8423 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java +++ b/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridge.java
@@ -9,6 +9,7 @@ import android.os.HandlerThread; import org.chromium.base.Callback; +import org.chromium.base.ServiceLoaderUtil; import org.chromium.base.ThreadUtils; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; @@ -32,10 +33,10 @@ public static PlatformServiceBridge getInstance() { synchronized (sInstanceLock) { if (sInstance == null) { - // Load an instance of PlatformServiceBridgeImpl. Because this can change - // depending on the GN configuration, this may not be the PlatformServiceBridgeImpl - // defined upstream. - sInstance = new PlatformServiceBridgeImpl(); + sInstance = ServiceLoaderUtil.maybeCreate(PlatformServiceBridge.class); + if (sInstance == null) { + sInstance = new NoOpPlatformServiceBridge(); + } } return sInstance; }
diff --git a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridgeImpl.java b/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridgeImpl.java deleted file mode 100644 index 2da7180..0000000 --- a/android_webview/java/src/org/chromium/android_webview/common/PlatformServiceBridgeImpl.java +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.android_webview.common; - -import org.chromium.build.annotations.NullMarked; - -/** - * Instantiable version of {@link PlatformServiceBridge}, don't add anything to this class! - * Downstream targets may provide a different implementation. In GN, we specify that - * {@link PlatformServiceBridge} is compiled separately from its implementation; other - * projects may specify a different PlatformServiceBridgeImpl via GN. - */ -@NullMarked -public class PlatformServiceBridgeImpl extends PlatformServiceBridge {}
diff --git a/android_webview/java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java b/android_webview/java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java index 9c6b6ef..b0fbfa8a 100644 --- a/android_webview/java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java +++ b/android_webview/java/src/org/chromium/android_webview/gfx/AwDrawFnImpl.java
@@ -6,6 +6,8 @@ import android.graphics.Canvas; +import androidx.annotation.VisibleForTesting; + import org.jni_zero.JNINamespace; import org.jni_zero.NativeMethods; @@ -16,7 +18,7 @@ @JNINamespace("android_webview") @Lifetime.WebView @NullMarked -public class AwDrawFnImpl implements AwFunctor { +public final class AwDrawFnImpl { private long mNativeAwDrawFnImpl; private final DrawFnAccess mAccess; private final int mHandle; @@ -32,7 +34,7 @@ mHandle = AwDrawFnImplJni.get().getFunctorHandle(mNativeAwDrawFnImpl, AwDrawFnImpl.this); } - @Override + /** Destroy on UI thread. Client should stop using CompositorFrameConsumer before this */ public void destroy() { assert mNativeAwDrawFnImpl != 0; AwDrawFnImplJni.get().releaseHandle(mNativeAwDrawFnImpl, AwDrawFnImpl.this); @@ -44,22 +46,30 @@ AwDrawFnImplJni.get().setDrawFnFunctionTable(functionTablePointer); } - @Override + /** Return the raw native pointer to CompositorFrameConsumer */ public long getNativeCompositorFrameConsumer() { assert mNativeAwDrawFnImpl != 0; return AwDrawFnImplJni.get() .getCompositorFrameConsumer(mNativeAwDrawFnImpl, AwDrawFnImpl.this); } - @Override + /** Insert draw functor into recording canvas */ public boolean requestDraw(Canvas canvas) { assert mNativeAwDrawFnImpl != 0; mAccess.drawWebViewFunctor(canvas, mHandle); return true; } - @Override - public void trimMemory() {} + /** + * Intended for test code. + * + * @return the number of references from WebView to this class. The remaining references are + * from Android libhwui. + */ + @VisibleForTesting + public static int getReferenceInstanceCount() { + return AwDrawFnImplJni.get().getReferenceInstanceCount(); + } @NativeMethods interface Natives { @@ -72,5 +82,7 @@ void setDrawFnFunctionTable(long functionTablePointer); long create(); + + int getReferenceInstanceCount(); } }
diff --git a/android_webview/java/src/org/chromium/android_webview/gfx/AwFunctor.java b/android_webview/java/src/org/chromium/android_webview/gfx/AwFunctor.java deleted file mode 100644 index 381d7e7..0000000 --- a/android_webview/java/src/org/chromium/android_webview/gfx/AwFunctor.java +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.android_webview.gfx; - -import android.graphics.Canvas; - -import org.chromium.build.annotations.NullMarked; - -/** - * Interface for functor implementation. This allows client to avoid differentiating between GL and - * Vulkan implementations. - */ -@NullMarked -public interface AwFunctor { - /** Insert draw functor into recording canvas */ - boolean requestDraw(Canvas canvas); - - /** Return the raw native pointer to CompositorFrameConsumer */ - long getNativeCompositorFrameConsumer(); - - /** Free memory */ - void trimMemory(); - - /** Destroy on UI thread. Client should stop using CompositorFrameConsumer before this */ - void destroy(); -}
diff --git a/android_webview/java/src/org/chromium/android_webview/gfx/AwGLFunctor.java b/android_webview/java/src/org/chromium/android_webview/gfx/AwGLFunctor.java deleted file mode 100644 index 0232161..0000000 --- a/android_webview/java/src/org/chromium/android_webview/gfx/AwGLFunctor.java +++ /dev/null
@@ -1,133 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.android_webview.gfx; - -import android.graphics.Canvas; -import android.view.ViewGroup; - -import androidx.annotation.VisibleForTesting; - -import org.jni_zero.CalledByNative; -import org.jni_zero.JNINamespace; -import org.jni_zero.NativeMethods; - -import org.chromium.android_webview.AwContents; -import org.chromium.android_webview.common.Lifetime; -import org.chromium.build.annotations.NullMarked; - -/** - * Manages state associated with the Android render thread and the draw functor that the WebView - * uses to render its contents. AwGLFunctor is responsible for managing the lifetime of native - * RenderThreadManager and HardwareRenderer, ensuring that they continue to exist while the functor - * remains attached to the render node hierarchy. - */ -@JNINamespace("android_webview") -@Lifetime.WebView -@NullMarked -public class AwGLFunctor implements AwFunctor { - private final long mNativeAwGLFunctor; - private final AwContents.NativeDrawGLFunctor mNativeDrawGLFunctor; - private final ViewGroup mContainerView; - private final Runnable mFunctorReleasedCallback; - // Counts outstanding requestDrawGL calls as well as window attach count. - private int mRefCount; - - public AwGLFunctor( - AwContents.NativeDrawFunctorFactory nativeDrawFunctorFactory, ViewGroup containerView) { - mNativeAwGLFunctor = AwGLFunctorJni.get().create(this); - mNativeDrawGLFunctor = nativeDrawFunctorFactory.createGLFunctor(mNativeAwGLFunctor); - mContainerView = containerView; - mFunctorReleasedCallback = this::removeReference; - addReference(); - } - - @Override - public void destroy() { - assert mRefCount > 0; - AwGLFunctorJni.get() - .removeFromCompositorFrameProducer(mNativeAwGLFunctor, AwGLFunctor.this); - removeReference(); - } - - public static long getAwDrawGLFunction() { - return AwGLFunctorJni.get().getAwDrawGLFunction(); - } - - @Override - public long getNativeCompositorFrameConsumer() { - assert mRefCount > 0; - return AwGLFunctorJni.get() - .getCompositorFrameConsumer(mNativeAwGLFunctor, AwGLFunctor.this); - } - - @Override - public boolean requestDraw(Canvas canvas) { - assert mRefCount > 0; - boolean success = mNativeDrawGLFunctor.requestDrawGL(canvas, mFunctorReleasedCallback); - if (success) { - addReference(); - } - return success; - } - - private void addReference() { - ++mRefCount; - } - - private void removeReference() { - assert mRefCount > 0; - if (--mRefCount == 0) { - // When |mRefCount| decreases to zero, the functor is neither attached to a view, nor - // referenced from the render tree, and so it is safe to delete the HardwareRenderer - // instance to free up resources because the current state will not be drawn again. - AwGLFunctorJni.get().deleteHardwareRenderer(mNativeAwGLFunctor, AwGLFunctor.this); - mNativeDrawGLFunctor.destroy(); - AwGLFunctorJni.get().destroy(mNativeAwGLFunctor); - } - } - - @CalledByNative - private boolean requestInvokeGL(boolean waitForCompletion) { - return mNativeDrawGLFunctor.requestInvokeGL(mContainerView, waitForCompletion); - } - - @CalledByNative - private void detachFunctorFromView() { - mNativeDrawGLFunctor.detach(mContainerView); - mContainerView.invalidate(); - } - - @Override - public void trimMemory() { - assert mRefCount > 0; - AwGLFunctorJni.get().deleteHardwareRenderer(mNativeAwGLFunctor, AwGLFunctor.this); - } - - /** - * Intended for test code. - * @return the number of native instances of this class. - */ - @VisibleForTesting - public static int getNativeInstanceCount() { - return AwGLFunctorJni.get().getNativeInstanceCount(); - } - - @NativeMethods - interface Natives { - void deleteHardwareRenderer(long nativeAwGLFunctor, AwGLFunctor caller); - - void removeFromCompositorFrameProducer(long nativeAwGLFunctor, AwGLFunctor caller); - - long getCompositorFrameConsumer(long nativeAwGLFunctor, AwGLFunctor caller); - - long getAwDrawGLFunction(); - - void destroy(long nativeAwGLFunctor); - - long create(AwGLFunctor javaProxy); - - int getNativeInstanceCount(); - } -}
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java index dd4072b..f3b28df 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java
@@ -27,10 +27,10 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.DependencyFactory; import org.chromium.android_webview.AwContents.InternalAccessDelegate; -import org.chromium.android_webview.AwContents.NativeDrawFunctorFactory; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.AwWebResourceRequest; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.test.util.GraphicsTestUtils; import org.chromium.android_webview.test.util.JSUtils; import org.chromium.base.Log; @@ -526,7 +526,7 @@ testContainerView, testContainerView.getContext(), testContainerView.getInternalAccessDelegate(), - testContainerView.getNativeDrawFunctorFactory(), + testContainerView.getDrawFnAccess(), awContentsClient, awSettings, testDependencyFactory); @@ -917,7 +917,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -926,7 +926,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java index 97dfcb1..dd2bad7 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsGarbageCollectionTest.java
@@ -30,7 +30,7 @@ import org.junit.runners.Parameterized.UseParametersRunnerFactory; import org.chromium.android_webview.AwContents; -import org.chromium.android_webview.gfx.AwGLFunctor; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory; import org.chromium.base.BaseFeatures; import org.chromium.base.ThreadUtils; @@ -425,7 +425,7 @@ () -> { return Pair.create( AwContents.getNativeInstanceCount(), - AwGLFunctor.getNativeInstanceCount()); + AwDrawFnImpl.getReferenceInstanceCount()); }); } catch (Exception e) { throw new CriteriaNotSatisfiedException(e); @@ -433,7 +433,7 @@ Criteria.checkThat( "AwContents count", (int) nativeCounts.first, Matchers.is(0)); Criteria.checkThat( - "AwGLFunctor count", (int) nativeCounts.second, Matchers.is(0)); + "DrawFunctor count", (int) nativeCounts.second, Matchers.is(0)); }; // Depending on a single gc call can make this test flaky. It's possible
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwMediaIntegrityApiTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwMediaIntegrityApiTest.java index a05a6cb..4b350dcc 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwMediaIntegrityApiTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwMediaIntegrityApiTest.java
@@ -26,8 +26,8 @@ import org.chromium.android_webview.common.MediaIntegrityErrorCode; import org.chromium.android_webview.common.MediaIntegrityErrorWrapper; import org.chromium.android_webview.common.MediaIntegrityProvider; +import org.chromium.android_webview.common.NoOpPlatformServiceBridge; import org.chromium.android_webview.common.PlatformServiceBridge; -import org.chromium.android_webview.common.PlatformServiceBridgeImpl; import org.chromium.android_webview.common.ValueOrErrorCallback; import org.chromium.android_webview.test.AwActivityTestRule.TestDependencyFactory; import org.chromium.base.ThreadUtils; @@ -1065,7 +1065,7 @@ } /** PlatformServiceBridge where MediaIntegrityProvider responses can be queued. */ - private static class MockPlatformServiceBridge extends PlatformServiceBridgeImpl { + private static class MockPlatformServiceBridge extends NoOpPlatformServiceBridge { private static class CallKey {
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java index 2e456a0d..52c7f70 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/LoadUrlTest.java
@@ -27,11 +27,11 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.DependencyFactory; import org.chromium.android_webview.AwContents.InternalAccessDelegate; -import org.chromium.android_webview.AwContents.NativeDrawFunctorFactory; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwContentsClient.AwWebResourceError; import org.chromium.android_webview.AwSettings; import org.chromium.android_webview.WebviewErrorCode; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.JSUtils; import org.chromium.base.ThreadUtils; @@ -815,7 +815,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -824,7 +824,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java index 80f2da9b..06f2bcc 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
@@ -29,7 +29,6 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.DependencyFactory; import org.chromium.android_webview.AwContents.InternalAccessDelegate; -import org.chromium.android_webview.AwContents.NativeDrawFunctorFactory; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwContentsStatics; import org.chromium.android_webview.AwSettings; @@ -38,6 +37,7 @@ import org.chromium.android_webview.WebviewErrorCode; import org.chromium.android_webview.common.AwSwitches; import org.chromium.android_webview.common.PlatformServiceBridge; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.safe_browsing.AwSafeBrowsingConfigHelper; import org.chromium.android_webview.safe_browsing.AwSafeBrowsingConversionHelper; import org.chromium.android_webview.safe_browsing.AwSafeBrowsingResponse; @@ -197,7 +197,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -206,7 +206,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory); @@ -281,7 +281,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -290,7 +290,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContents.java b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContents.java index a24fb74..da1a357 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContents.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/TestAwContents.java
@@ -11,6 +11,7 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwSettings; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import java.util.ArrayList; @@ -39,7 +40,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -48,7 +49,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java index 223d6d8..76eab21 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/VisualStateCallbackTest.java
@@ -23,10 +23,10 @@ import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents.DependencyFactory; import org.chromium.android_webview.AwContents.InternalAccessDelegate; -import org.chromium.android_webview.AwContents.NativeDrawFunctorFactory; import org.chromium.android_webview.AwContentsClient; import org.chromium.android_webview.AwRenderProcessGoneDetail; import org.chromium.android_webview.AwSettings; +import org.chromium.android_webview.gfx.AwDrawFnImpl; import org.chromium.android_webview.test.AwActivityTestRule; import org.chromium.android_webview.test.AwJUnit4ClassRunnerWithParameters; import org.chromium.android_webview.test.AwParameterizedTest; @@ -74,7 +74,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -83,7 +83,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory); @@ -105,7 +105,7 @@ ViewGroup containerView, Context context, InternalAccessDelegate internalAccessAdapter, - NativeDrawFunctorFactory nativeDrawFunctorFactory, + AwDrawFnImpl.DrawFnAccess drawFnAccess, AwContentsClient contentsClient, AwSettings settings, DependencyFactory dependencyFactory) { @@ -114,7 +114,7 @@ containerView, context, internalAccessAdapter, - nativeDrawFunctorFactory, + drawFnAccess, contentsClient, settings, dependencyFactory);
diff --git a/android_webview/public/BUILD.gn b/android_webview/public/BUILD.gn index 7e15b05..bc04f61 100644 --- a/android_webview/public/BUILD.gn +++ b/android_webview/public/BUILD.gn
@@ -5,7 +5,6 @@ source_set("public") { sources = [ "browser/draw_fn.h", - "browser/draw_gl.h", "browser/draw_sw.h", ] }
diff --git a/android_webview/public/browser/draw_gl.h b/android_webview/public/browser/draw_gl.h deleted file mode 100644 index 66d25da..0000000 --- a/android_webview/public/browser/draw_gl.h +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_GL_H_ -#define ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_GL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// 1 is L/L MR1 -// -// 2 starts at M, and added an imperfect workaround for complex clipping by -// elevating the WebView into an FBO layer. If any transform, clip, or outline -// clip occurs that would either likely use the stencil buffer for clipping, or -// require shader based clipping in HWUI, the WebView is drawn into an FBO (if -// it fits). -// This is a temporary workaround for a lack of WebView support for stencil/ -// shader based round rect clipping, and should be removed when webview is -// capable of supporting these clips internally when drawing. -// -// 3 starts during development of P, when android defaults from HWUI to skia as -// the GL renderer. Skia already maintains and restores its GL state, so there -// is no need for WebView to restore this state. Skia also no longer promises -// GL state on entering draw, such as no vertex array buffer binding. -static const int kAwDrawGLInfoVersion = 3; - -// Holds the information required to trigger an OpenGL drawing operation. -struct AwDrawGLInfo { - int version; // The AwDrawGLInfo this struct was built with. - - // Input: tells the draw function what action to perform. - enum Mode { - kModeDraw = 0, - kModeProcess = 1, - kModeProcessNoContext = 2, - kModeSync = 3, - } mode; - - // Input: current clip rect in surface coordinates. Reflects the current state - // of the OpenGL scissor rect. Both the OpenGL scissor rect and viewport are - // set by the caller of the draw function and updated during View animations. - int clip_left; - int clip_top; - int clip_right; - int clip_bottom; - - // Input: current width/height of destination surface. - int width; - int height; - - // Input: is the View rendered into an independent layer. - // If false, the surface is likely to hold to the full screen contents, with - // the scissor box set by the caller to the actual View location and size. - // Also the transformation matrix will contain at least a translation to the - // position of the View to render, plus any other transformations required as - // part of any ongoing View animation. View translucency (alpha) is ignored, - // although the framework will set is_layer to true for non-opaque cases. - // Can be requested via the View.setLayerType(View.LAYER_TYPE_NONE, ...) - // Android API method. - // - // If true, the surface is dedicated to the View and should have its size. - // The viewport and scissor box are set by the caller to the whole surface. - // Animation transformations are handled by the caller and not reflected in - // the provided transformation matrix. Translucency works normally. - // Can be requested via the View.setLayerType(View.LAYER_TYPE_HARDWARE, ...) - // Android API method. - bool is_layer; - - // Input: current transformation matrix in surface pixels. - // Uses the column-based OpenGL matrix format. - float transform[16]; -}; - -// Function to invoke a direct GL draw into the client's pre-configured -// GL context. Obtained via AwContents.getDrawGLFunction() (static). -// |view_context| is an opaque identifier that was returned by the corresponding -// call to AwContents.getAwDrawGLViewContext(). -// |draw_info| carries the in and out parameters for this draw. -// |spare| ignored; pass NULL. -typedef void (AwDrawGLFunction)(long view_context, - AwDrawGLInfo* draw_info, - void* spare); -enum AwMapMode { - MAP_READ_ONLY = 0, - MAP_WRITE_ONLY = 1, - MAP_READ_WRITE = 2, -}; - -// Called to create a GraphicBuffer -typedef long AwCreateGraphicBufferFunction(int w, int h); -// Called to release a GraphicBuffer -typedef void AwReleaseGraphicBufferFunction(long buffer_id); -// Called to map a GraphicBuffer in |mode|. -typedef int AwMapFunction(long buffer_id, AwMapMode mode, void** vaddr); -// Called to unmap a GraphicBuffer -typedef int AwUnmapFunction(long buffer_id); -// Called to get a native buffer pointer -typedef void* AwGetNativeBufferFunction(long buffer_id); -// Called to get the stride of the buffer -typedef unsigned int AwGetStrideFunction(long buffer_id); - -static const int kAwDrawGLFunctionTableVersion = 1; - -// Set of functions used in rendering in hardware mode -struct AwDrawGLFunctionTable { - int version; - AwCreateGraphicBufferFunction* create_graphic_buffer; - AwReleaseGraphicBufferFunction* release_graphic_buffer; - AwMapFunction* map; - AwUnmapFunction* unmap; - AwGetNativeBufferFunction* get_native_buffer; - AwGetStrideFunction* get_stride; -}; - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // ANDROID_WEBVIEW_PUBLIC_BROWSER_DRAW_GL_H_
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn index abb955e3..7fb3d0f 100644 --- a/android_webview/test/BUILD.gn +++ b/android_webview/test/BUILD.gn
@@ -193,7 +193,6 @@ base_webview_instrumentation_apk("webview_instrumentation_apk") { deps = [ - "//android_webview:platform_service_bridge_upstream_implementation_java", # Note: you probably don't want to add any more deps here. This is the # upstream instantiation of 'base_webview_instrumentation_apk', however # there is also another instance of 'base_webview_instrumentation_apk'
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java index 421a98e..9ad2117 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java
@@ -263,7 +263,7 @@ testContainerView, testContainerView.getContext(), testContainerView.getInternalAccessDelegate(), - testContainerView.getNativeDrawFunctorFactory(), + testContainerView.getDrawFnAccess(), awContentsClient, awSettings)); testContainerView.getAwContents().getSettings().setJavaScriptEnabled(true);
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java index 41acc1f..f454cc4 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java
@@ -274,8 +274,8 @@ return mAwContents; } - public AwContents.NativeDrawFunctorFactory getNativeDrawFunctorFactory() { - return new NativeDrawFunctorFactory(); + public AwDrawFnImpl.DrawFnAccess getDrawFnAccess() { + return new DrawFnAccess(); } public AwContents.InternalAccessDelegate getInternalAccessDelegate() { @@ -422,18 +422,6 @@ return mAwContents.getViewMethods().onDragEvent(event); } - private class NativeDrawFunctorFactory implements AwContents.NativeDrawFunctorFactory { - @Override - public AwContents.NativeDrawGLFunctor createGLFunctor(long context) { - return null; - } - - @Override - public AwDrawFnImpl.DrawFnAccess getDrawFnAccess() { - return new DrawFnAccess(); - } - } - private class DrawFnAccess implements AwDrawFnImpl.DrawFnAccess { @Override public void drawWebViewFunctor(Canvas canvas, int functor) {
diff --git a/android_webview/variables.gni b/android_webview/variables.gni index f6e89f0..29e43a53 100644 --- a/android_webview/variables.gni +++ b/android_webview/variables.gni
@@ -13,9 +13,6 @@ webview_devui_show_icon = android_channel != "stable" } -upstream_only_webview_deps = [ - "//android_webview:platform_service_bridge_upstream_implementation_java", - "//android_webview/nonembedded:icon_resources", -] +upstream_only_webview_deps = [ "//android_webview/nonembedded:icon_resources" ] webview_product_config_java_package = "org.chromium.android_webview"
diff --git a/ash/system/power/power_button_controller_unittest.cc b/ash/system/power/power_button_controller_unittest.cc index 635f4be..5982fcd 100644 --- a/ash/system/power/power_button_controller_unittest.cc +++ b/ash/system/power/power_button_controller_unittest.cc
@@ -956,7 +956,6 @@ // painted as active to avoid frame color change. EXPECT_FALSE(widget->IsActive()); EXPECT_TRUE(widget->ShouldPaintAsActive()); - EXPECT_TRUE(widget->non_client_view()->frame_view()->ShouldPaintAsActive()); EXPECT_TRUE( wm::IsActiveWindow(power_button_test_api_->GetPowerButtonMenuView() ->GetWidget()
diff --git a/base/BUILD.gn b/base/BUILD.gn index 1c383e0..17963f8 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -29,7 +29,6 @@ import("//build/config/cronet/config.gni") import("//build/config/dcheck_always_on.gni") import("//build/config/logging.gni") -import("//build/config/nacl/config.gni") import("//build/config/profiling/profiling.gni") import("//build/config/rust.gni") import("//build/config/sanitizers/sanitizers.gni") @@ -97,9 +96,6 @@ (is_castos || is_cast_android || is_android), "Do not enable PI mutexes without consulting the security team") -assert(!is_nacl || is_nacl_saigo, - "base must not be built in most nacl toolchains") - # Prevent //base having to support a toolchain that uses a different # llvm/libc++ version. assert(!is_wasm, "base must not be built in most wasm toolchains") @@ -329,8 +325,6 @@ "hash/legacy_hash.cc", "hash/legacy_hash.h", "json/json_common.h", - "json/json_parser.cc", - "json/json_parser.h", "json/json_reader.cc", "json/json_reader.h", "json/json_string_value_serializer.cc", @@ -1054,16 +1048,14 @@ "//build/config/compiler:compiler_buildflags", "//third_party/modp_b64", ] - if (!is_nacl) { - # Used by metrics/crc32, except on NaCl builds. - deps += [ "//third_party/zlib" ] - # NaCl does not support Rust. - deps += [ - ":rust_logger", - "//third_party/rust/serde_json_lenient/v0_2/wrapper", - ] - } + # Used by metrics/crc32 + deps += [ "//third_party/zlib" ] + + deps += [ + ":rust_logger", + "//third_party/rust/serde_json_lenient/v0_2/wrapper", + ] # `raw_ptr` cannot be made a component due to CRT symbol issues. # Its gateway to being a component is through `//base`, so we have @@ -1098,16 +1090,14 @@ "//third_party/abseil-cpp:absl", ] - if (!is_nacl) { - sources += [ - "containers/span_rust.h", - "strings/string_view_rust.h", - ] + sources += [ + "containers/span_rust.h", + "strings/string_view_rust.h", + ] - # Base provides conversions between CXX types and base types (e.g. - # std::string_view). - public_deps += [ "//build/rust:cxx_cppdeps" ] - } + # Base provides conversions between CXX types and base types (e.g. + # std::string_view). + public_deps += [ "//build/rust:cxx_cppdeps" ] # Needed for <atomic> if using newer C++ library than sysroot, except if # building inside the cros_sdk environment - use host_toolchain as a @@ -1539,245 +1529,205 @@ public_configs = [ ":fuchsia_sync_lib" ] } - # Several helpers in //base are backed by BoringSSL; however, NaCl builds - # cannot easily depend on BoringSSL due to the nacl_io library, so NaCl builds - # still retain a dedicated local implementation of the functionality. - # - # TODO(crbug.com/40511454) Use only boringssl when NaCl is removed. sources += [ + "hash/md5.cc", "hash/md5.h", + "hash/sha1.cc", "hash/sha1.h", ] - if (is_nacl) { + public_deps += [ "//third_party/boringssl" ] + + sources += [ + "base_paths.cc", + "base_paths.h", + "cpu.cc", + "cpu.h", + "debug/crash_logging.cc", + "debug/crash_logging.h", + "debug/stack_trace.cc", + "debug/stack_trace.h", + "files/drive_info.cc", + "files/drive_info.h", + "files/file_enumerator.cc", + "files/file_enumerator.h", + "files/file_proxy.cc", + "files/file_proxy.h", + "files/file_util.cc", + "files/file_util.h", + "files/important_file_writer.cc", + "files/important_file_writer.h", + "files/important_file_writer_cleaner.cc", + "files/important_file_writer_cleaner.h", + "files/scoped_temp_dir.cc", + "files/scoped_temp_dir.h", + "files/scoped_temp_file.cc", + "files/scoped_temp_file.h", + "json/json_file_value_serializer.cc", + "json/json_file_value_serializer.h", + "logging/rust_log_integration.cc", + "logging/rust_log_integration.h", + "memory/discardable_memory.cc", + "memory/discardable_memory.h", + "memory/discardable_memory_allocator.cc", + "memory/discardable_memory_allocator.h", + "memory/discardable_memory_internal.h", + "metrics/persistent_histogram_storage.cc", + "metrics/persistent_histogram_storage.h", + "native_library.cc", + "native_library.h", + "path_service.cc", + "path_service.h", + "process/process_metrics.cc", + "process/process_metrics.h", + "scoped_native_library.cc", + "scoped_native_library.h", + "system/sys_info.cc", + "system/sys_info.h", + "system/sys_info_internal.h", + "task/thread_pool/initialization_util.cc", + "task/thread_pool/initialization_util.h", + ] + + if (is_win) { sources += [ - "hash/md5_nacl.cc", - "hash/md5_nacl.h", - "hash/sha1_nacl.cc", - "hash/sha1_nacl.h", + "base_paths_win.cc", + "base_paths_win.h", ] - } else { - sources += [ - "hash/md5_boringssl.cc", - "hash/md5_boringssl.h", - "hash/sha1_boringssl.cc", - "hash/sha1_boringssl.h", - ] - public_deps += [ "//third_party/boringssl" ] } - # NaCl. - if (is_nacl) { - # Explicitly include the linux file. + if (is_apple) { sources += [ - "debug/stack_trace_nacl.cc", - "files/file_path_watcher_stub.cc", - "memory/page_size_nacl.cc", - "os_compat_nacl.cc", - "os_compat_nacl.h", - "process/process_stubs.cc", - "rand_util_nacl.cc", - "sync_socket_nacl.cc", - "system/sys_info_nacl.cc", - "threading/platform_thread_linux_base.cc", - "threading/platform_thread_nacl.cc", + "base_paths_apple.cc", + "base_paths_apple.h", ] - } else { + } + + if (is_mac) { sources += [ - "base_paths.cc", - "base_paths.h", - "cpu.cc", - "cpu.h", - "debug/crash_logging.cc", - "debug/crash_logging.h", - "debug/stack_trace.cc", - "debug/stack_trace.h", - "files/drive_info.cc", - "files/drive_info.h", - "files/file_enumerator.cc", - "files/file_enumerator.h", - "files/file_proxy.cc", - "files/file_proxy.h", - "files/file_util.cc", - "files/file_util.h", - "files/important_file_writer.cc", - "files/important_file_writer.h", - "files/important_file_writer_cleaner.cc", - "files/important_file_writer_cleaner.h", - "files/scoped_temp_dir.cc", - "files/scoped_temp_dir.h", - "files/scoped_temp_file.cc", - "files/scoped_temp_file.h", - "json/json_file_value_serializer.cc", - "json/json_file_value_serializer.h", - "logging/rust_log_integration.cc", - "logging/rust_log_integration.h", - "memory/discardable_memory.cc", - "memory/discardable_memory.h", - "memory/discardable_memory_allocator.cc", - "memory/discardable_memory_allocator.h", - "memory/discardable_memory_internal.h", - "metrics/persistent_histogram_storage.cc", - "metrics/persistent_histogram_storage.h", - "native_library.cc", - "native_library.h", - "path_service.cc", - "path_service.h", - "process/process_metrics.cc", - "process/process_metrics.h", - "scoped_native_library.cc", - "scoped_native_library.h", - "system/sys_info.cc", - "system/sys_info.h", - "system/sys_info_internal.h", - "task/thread_pool/initialization_util.cc", - "task/thread_pool/initialization_util.h", + "base_paths_mac.h", + "base_paths_mac.mm", + ] + } + + if (is_android) { + sources += [ + "base_paths_android.cc", + "base_paths_android.h", + ] + } + + if (is_posix) { + sources += [ + "base_paths_posix.h", + "memory/madv_free_discardable_memory_allocator_posix.cc", + "memory/madv_free_discardable_memory_allocator_posix.h", + "memory/madv_free_discardable_memory_posix.cc", + "memory/madv_free_discardable_memory_posix.h", + "posix/unix_domain_socket.cc", + "posix/unix_domain_socket.h", + "rand_util_posix.cc", + "system/sys_info_posix.cc", + ] + } + + if (is_posix || is_fuchsia) { + sources += [ + "files/file_descriptor_watcher_posix.cc", + "files/file_descriptor_watcher_posix.h", + "files/file_enumerator_posix.cc", + "files/file_util_posix.cc", + "memory/page_size_posix.cc", ] - if (is_win) { - sources += [ - "base_paths_win.cc", - "base_paths_win.h", - ] + if (!is_apple) { + sources += [ "files/drive_info_posix.cc" ] } + } - if (is_apple) { - sources += [ - "base_paths_apple.cc", - "base_paths_apple.h", - ] - } + if ((is_posix && !is_ios) || is_fuchsia) { + sources += [ + "process/process_metrics_posix.cc", + "sync_socket_posix.cc", + ] + } - if (is_mac) { - sources += [ - "base_paths_mac.h", - "base_paths_mac.mm", - ] - } + if (is_posix && !is_apple) { + sources += [ + "native_library_posix.cc", + "posix/can_lower_nice_to.cc", + "posix/can_lower_nice_to.h", + "process/launch_posix.cc", + "profiler/module_cache_posix.cc", + "profiler/stack_base_address_posix.cc", + "profiler/stack_base_address_posix.h", + "profiler/stack_copier_signal.cc", + "profiler/stack_copier_signal.h", + "profiler/thread_delegate_posix.cc", + "profiler/thread_delegate_posix.h", + ] + } - if (is_android) { - sources += [ - "base_paths_android.cc", - "base_paths_android.h", - ] - } + if (is_posix && !is_android) { + sources += [ "debug/stack_trace_posix.cc" ] + } + + if (is_posix && !is_ios) { + sources += [ "process/process_posix.cc" ] + } + if (!is_win && !is_chromeos && !is_android && !is_linux) { + sources += [ "synchronization/cancelable_event_default.cc" ] + } + + if (is_linux || is_chromeos || is_android) { + sources += [ "synchronization/cancelable_event_posix.cc" ] + } + + if (use_blink) { + sources += [ + "memory/discardable_shared_memory.cc", + "memory/discardable_shared_memory.h", + "memory/shared_memory_switch.cc", + "memory/shared_memory_switch.h", + "metrics/histogram_shared_memory.cc", + "metrics/histogram_shared_memory.h", + "process/kill.cc", + "process/kill.h", + "process/launch.cc", + "process/launch.h", + "process/memory.cc", + "process/memory.h", + "process/process_iterator.cc", + "process/process_iterator.h", + ] if (is_posix) { - sources += [ - "base_paths_posix.h", - "memory/madv_free_discardable_memory_allocator_posix.cc", - "memory/madv_free_discardable_memory_allocator_posix.h", - "memory/madv_free_discardable_memory_posix.cc", - "memory/madv_free_discardable_memory_posix.h", - "posix/unix_domain_socket.cc", - "posix/unix_domain_socket.h", - "rand_util_posix.cc", - "system/sys_info_posix.cc", - ] + sources += [ "process/kill_posix.cc" ] } + } - if (is_posix || is_fuchsia) { - sources += [ - "files/file_descriptor_watcher_posix.cc", - "files/file_descriptor_watcher_posix.h", - "files/file_enumerator_posix.cc", - "files/file_util_posix.cc", - "memory/page_size_posix.cc", - ] - - if (!is_apple) { - sources += [ "files/drive_info_posix.cc" ] - } - } - - if ((is_posix && !is_ios) || is_fuchsia) { - sources += [ - "process/process_metrics_posix.cc", - "sync_socket_posix.cc", - ] - } - - if (is_posix && !is_apple) { - sources += [ - "native_library_posix.cc", - "posix/can_lower_nice_to.cc", - "posix/can_lower_nice_to.h", - "process/launch_posix.cc", - "profiler/module_cache_posix.cc", - "profiler/stack_base_address_posix.cc", - "profiler/stack_base_address_posix.h", - "profiler/stack_copier_signal.cc", - "profiler/stack_copier_signal.h", - "profiler/thread_delegate_posix.cc", - "profiler/thread_delegate_posix.h", - ] - } - - if (is_posix && !is_android) { - sources += [ "debug/stack_trace_posix.cc" ] - } - - if (is_posix && !is_ios) { - sources += [ "process/process_posix.cc" ] - } - if (!is_win && !is_chromeos && !is_android && !is_linux) { - sources += [ "synchronization/cancelable_event_default.cc" ] - } - - if (is_linux || is_chromeos || is_android) { - sources += [ "synchronization/cancelable_event_posix.cc" ] - } - - if (use_blink) { - sources += [ - "memory/discardable_shared_memory.cc", - "memory/discardable_shared_memory.h", - "memory/shared_memory_switch.cc", - "memory/shared_memory_switch.h", - "metrics/histogram_shared_memory.cc", - "metrics/histogram_shared_memory.h", - "process/kill.cc", - "process/kill.h", - "process/launch.cc", - "process/launch.h", - "process/memory.cc", - "process/memory.h", - "process/process_iterator.cc", - "process/process_iterator.h", - ] - - if (is_posix) { - sources += [ "process/kill_posix.cc" ] - } - } - - if (is_linux || is_chromeos) { - sources += [ - "base_paths_posix.cc", - "debug/elf_reader.cc", - "debug/elf_reader.h", - "stack_canary_linux.cc", - "stack_canary_linux.h", - ] - } - if (use_partition_alloc) { - # Add stuff that doesn't work in NaCl or other environments that disable - # partition_alloc. - sources += [ - "allocator/dispatcher/memory_tagging.cc", - "allocator/dispatcher/memory_tagging.h", - - # PartitionAlloc uses SpinLock, which doesn't work in NaCl (see below). - "allocator/miracle_parameter.cc", - "allocator/miracle_parameter.h", - "allocator/partition_alloc_features.cc", - "allocator/partition_alloc_features.h", - "allocator/partition_alloc_support.cc", - "allocator/partition_alloc_support.h", - ] - } - if (use_allocator_shim) { - public_deps += [ "allocator/partition_allocator:allocator_shim" ] - } + if (is_linux || is_chromeos) { + sources += [ + "base_paths_posix.cc", + "debug/elf_reader.cc", + "debug/elf_reader.h", + "stack_canary_linux.cc", + "stack_canary_linux.h", + ] + } + if (use_partition_alloc) { + sources += [ + "allocator/dispatcher/memory_tagging.cc", + "allocator/dispatcher/memory_tagging.h", + "allocator/miracle_parameter.cc", + "allocator/miracle_parameter.h", + "allocator/partition_alloc_features.cc", + "allocator/partition_alloc_features.h", + "allocator/partition_alloc_support.cc", + "allocator/partition_alloc_support.h", + ] + } + if (use_allocator_shim) { + public_deps += [ "allocator/partition_allocator:allocator_shim" ] } # Windows. @@ -3248,7 +3198,7 @@ } } -if (!is_nacl && (is_linux || is_chromeos)) { +if (is_linux || is_chromeos) { # This test must compile with -fstack-protector-all source_set("stack_canary_linux_unittests") { testonly = true @@ -3446,7 +3396,6 @@ "i18n/timezone_unittest.cc", "i18n/transliterator_unittest.cc", "immediate_crash_unittest.cc", - "json/json_parser_unittest.cc", "json/json_reader_unittest.cc", "json/json_value_converter_unittest.cc", "json/json_value_serializer_unittest.cc", @@ -3743,12 +3692,10 @@ sources += [ "location_unittest.cc" ] } - if (!is_nacl) { - sources += [ - "containers/span_rust_unittest.cc", - "strings/string_piece_rust_unittest.cc", - ] - } + sources += [ + "containers/span_rust_unittest.cc", + "strings/string_piece_rust_unittest.cc", + ] if (use_safe_libcxx || use_safe_libstdcxx) { sources += [ "libcpp_hardening_test.cc" ] @@ -3798,9 +3745,7 @@ deps += [ "allocator/partition_allocator/src/partition_alloc:unittests" ] } - if (!is_nacl) { - deps += [ "//build/rust:cxx_cppdeps" ] - } + deps += [ "//build/rust:cxx_cppdeps" ] data_deps = [ "//base/test:immediate_crash_test_helper", @@ -3946,9 +3891,7 @@ "process/set_process_title_linux_unittest.cc", ] - if (!is_nacl) { - deps += [ ":stack_canary_linux_unittests" ] - } + deps += [ ":stack_canary_linux_unittests" ] } sources += [ "test/test_trace_processor_example_unittest.cc" ] @@ -3964,7 +3907,7 @@ "posix/file_descriptor_shuffle_unittest.cc", "posix/unix_domain_socket_unittest.cc", ] - if (!is_nacl && !is_apple) { + if (!is_apple) { sources += [ "profiler/stack_base_address_posix_unittest.cc", "profiler/stack_copier_signal_unittest.cc",
diff --git a/base/allocator/partition_allocator/gn/BUILDCONFIG.gn b/base/allocator/partition_allocator/gn/BUILDCONFIG.gn index 173fbfd..13120e2 100644 --- a/base/allocator/partition_allocator/gn/BUILDCONFIG.gn +++ b/base/allocator/partition_allocator/gn/BUILDCONFIG.gn
@@ -48,7 +48,6 @@ is_ios = current_os == "ios" is_linux = current_os == "linux" is_mac = current_os == "mac" -is_nacl = false is_win = current_os == "win" || current_os == "winuwp" is_cast_android = false is_castos = false
diff --git a/base/allocator/partition_allocator/partition_alloc.gni b/base/allocator/partition_allocator/partition_alloc.gni index c84e6691..9bdb5f8 100644 --- a/base/allocator/partition_allocator/partition_alloc.gni +++ b/base/allocator/partition_allocator/partition_alloc.gni
@@ -65,12 +65,8 @@ # Whether 64-bit pointers are used. # A static_assert in partition_alloc_config.h verifies that. -if (is_nacl) { - # NaCl targets don't use 64-bit pointers. - has_64_bit_pointers = false -} else if (current_cpu == "x64" || current_cpu == "arm64" || - current_cpu == "arm64e" || current_cpu == "loong64" || - current_cpu == "riscv64") { +if (current_cpu == "x64" || current_cpu == "arm64" || current_cpu == "arm64e" || + current_cpu == "loong64" || current_cpu == "riscv64") { assert(current_cpu != "arm64e" || (is_ios && target_environment == "device")) has_64_bit_pointers = true } else if (current_cpu == "x86" || current_cpu == "arm" || @@ -123,7 +119,7 @@ # and doesn't wish to incur the library size increase (crbug.com/674570). # 2. On NaCl (through this declaration), where PartitionAlloc doesn't # build at all. - use_partition_alloc = !is_nacl && is_clang_or_gcc + use_partition_alloc = is_clang_or_gcc } if (!is_clang_or_gcc) { @@ -133,10 +129,6 @@ "PartitionAlloc's allocator shim does not support this compiler") } -if (is_nacl) { - assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl") -} - declare_args() { # PartitionAlloc-Everywhere (PA-E). Causes allocator_shim.cc to route # calls to PartitionAlloc, rather than some other platform allocator. @@ -168,9 +160,6 @@ !enable_allocator_shim_partition_alloc_dispatch_with_advanced_checks_support || use_partition_alloc_as_malloc, "PartitionAlloc with advanced checks requires PartitionAlloc itself.") -assert(!use_allocator_shim || !is_nacl, - "The allocator shim supports every platform, except nacl") - if (use_allocator_shim && is_win) { # It's hard to override CRT's malloc family in every case in the component # build, and it's very easy to override it partially and to be inconsistent
diff --git a/base/debug/stack_trace_nacl.cc b/base/debug/stack_trace_nacl.cc deleted file mode 100644 index 8a2c91b..0000000 --- a/base/debug/stack_trace_nacl.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/debug/stack_trace.h" - -namespace base { -namespace debug { - -StackTrace::StackTrace() = default; -StackTrace::StackTrace(size_t count) : StackTrace() {} -StackTrace::StackTrace(span<const void* const> trace) : StackTrace() {} - -void StackTrace::Print() const {} - -void StackTrace::OutputToStream(std::ostream* os) const {} - -std::string StackTrace::ToString() const { - return {}; -} - -std::string StackTrace::ToStringWithPrefix(cstring_view prefix_string) const { - return {}; -} - -std::ostream& operator<<(std::ostream& os, const StackTrace& s) { - return os; -} - -} // namespace debug -} // namespace base
diff --git a/base/feature_list.cc b/base/feature_list.cc index 835119a..439f49d 100644 --- a/base/feature_list.cc +++ b/base/feature_list.cc
@@ -101,14 +101,12 @@ void Fail(const Feature* feature, bool with_feature_allow_list) { // TODO(crbug.com/40237050): Enable this check on all platforms. #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) -#if !BUILDFLAG(IS_NACL) // Create a crash key with the name of the feature accessed too early, to // facilitate crash triage. SCOPED_CRASH_KEY_STRING256("FeatureList", "feature-accessed-too-early", feature->name); SCOPED_CRASH_KEY_BOOL("FeatureList", "early-access-allow-list", with_feature_allow_list); -#endif // !BUILDFLAG(IS_NACL) CHECK(!feature) << "Accessed feature " << feature->name << (with_feature_allow_list ? " which is not on the allow list passed to " @@ -618,10 +616,8 @@ // FeatureList instance, as the state of the involved Features might change // with the final FeatureList for this process. if (!g_feature_list_instance->IsEarlyAccessInstance()) { -#if !BUILDFLAG(IS_NACL) // Configured first because it takes precedence over the getrandom() trial. internal::ConfigureBoringSSLBackedRandBytesFieldTrial(); -#endif } #if BUILDFLAG(DCHECK_IS_CONFIGURABLE) @@ -898,11 +894,9 @@ if (pos != std::string::npos) { feature_name = std::string_view(value.data(), pos); trial = FieldTrialList::Find(value.substr(pos + 1)); -#if !BUILDFLAG(IS_NACL) // If the below DCHECK fires, it means a non-existent trial name was // specified via the "Feature<Trial" command-line syntax. DCHECK(trial) << "trial='" << value.substr(pos + 1) << "' does not exist"; -#endif // !BUILDFLAG(IS_NACL) } RegisterOverride(feature_name, overridden_state, trial);
diff --git a/base/hash/md5_boringssl.cc b/base/hash/md5.cc similarity index 96% rename from base/hash/md5_boringssl.cc rename to base/hash/md5.cc index f406bcf..7d68475a 100644 --- a/base/hash/md5_boringssl.cc +++ b/base/hash/md5.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/hash/md5_boringssl.h" +#include "base/hash/md5.h" #include <cstdint> #include <string>
diff --git a/base/hash/md5.h b/base/hash/md5.h index 4d35857..c9050eb 100644 --- a/base/hash/md5.h +++ b/base/hash/md5.h
@@ -5,18 +5,16 @@ #ifndef BASE_HASH_MD5_H_ #define BASE_HASH_MD5_H_ +#include <stdint.h> + +#include <array> #include <string> #include <string_view> #include "base/base_export.h" #include "base/containers/span.h" #include "build/build_config.h" - -#if BUILDFLAG(IS_NACL) -#include "base/hash/md5_nacl.h" -#else -#include "base/hash/md5_boringssl.h" -#endif +#include "third_party/boringssl/src/include/openssl/md5.h" // MD5 stands for Message Digest algorithm 5. // @@ -51,6 +49,15 @@ namespace base { +// The output of an MD5 operation. +struct MD5Digest { + std::array<uint8_t, MD5_DIGEST_LENGTH> a; +}; + +// Used for storing intermediate data during an MD5 computation. Callers +// should not access the data. +using MD5Context = MD5_CTX; + // Initializes the given MD5 context structure for subsequent calls to // MD5Update(). BASE_EXPORT void MD5Init(MD5Context* context);
diff --git a/base/hash/md5_boringssl.h b/base/hash/md5_boringssl.h deleted file mode 100644 index 2823cf2..0000000 --- a/base/hash/md5_boringssl.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_HASH_MD5_BORINGSSL_H_ -#define BASE_HASH_MD5_BORINGSSL_H_ - -#include <stdint.h> - -#include <array> - -#include "third_party/boringssl/src/include/openssl/md5.h" - -namespace base { - -// The output of an MD5 operation. -struct MD5Digest { - std::array<uint8_t, MD5_DIGEST_LENGTH> a; -}; - -// Used for storing intermediate data during an MD5 computation. Callers -// should not access the data. -typedef MD5_CTX MD5Context; - -} // namespace base - -#endif // BASE_HASH_MD5_BORINGSSL_H_
diff --git a/base/hash/md5_nacl.cc b/base/hash/md5_nacl.cc deleted file mode 100644 index 120f2093..0000000 --- a/base/hash/md5_nacl.cc +++ /dev/null
@@ -1,297 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// The original file was copied from sqlite, and was in the public domain. - -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - */ - -#include "base/hash/md5.h" - -#include <stddef.h> -#include <string.h> - -#include <string_view> - -#include "base/containers/span.h" -#include "base/strings/string_number_conversions.h" - -namespace { - -struct Context { - uint32_t buf[4]; - uint32_t bits[2]; - uint8_t in[64]; -}; - -/* - * Note: this code is harmless on little-endian machines. - */ -void byteReverse(uint8_t* buf, unsigned longs) { - do { - uint32_t temp = - static_cast<uint32_t>(static_cast<unsigned>(buf[3]) << 8 | buf[2]) - << 16 | - (static_cast<unsigned>(buf[1]) << 8 | buf[0]); - *reinterpret_cast<uint32_t*>(buf) = temp; - buf += 4; - } while (--longs); -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void MD5Transform(uint32_t buf[4], const uint32_t in[16]) { - uint32_t a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -} // namespace - -namespace base { - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void MD5Init(MD5Context* context) { - struct Context* ctx = reinterpret_cast<struct Context*>(context); - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void MD5Update(MD5Context* context, std::string_view data) { - MD5Update(context, base::as_byte_span(data)); -} - -void MD5Update(MD5Context* context, base::span<const uint8_t> data) { - struct Context* ctx = reinterpret_cast<struct Context*>(context); - const uint8_t* buf = data.data(); - size_t len = data.size(); - - /* Update bitcount */ - - uint32_t t = ctx->bits[0]; - if ((ctx->bits[0] = t + (static_cast<uint32_t>(len) << 3)) < t) { - ctx->bits[1]++; /* Carry from low to high */ - } - ctx->bits[1] += static_cast<uint32_t>(len >> 29); - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - uint8_t* p = static_cast<uint8_t*>(ctx->in + t); - - t = 64 - t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void MD5Final(MD5Digest* digest, MD5Context* context) { - struct Context* ctx = reinterpret_cast<struct Context*>(context); - unsigned count; - uint8_t* p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - memcpy(&ctx->in[14 * sizeof(ctx->bits[0])], &ctx->bits[0], - sizeof(ctx->bits[0])); - memcpy(&ctx->in[15 * sizeof(ctx->bits[1])], &ctx->bits[1], - sizeof(ctx->bits[1])); - - MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); - byteReverse(reinterpret_cast<uint8_t*>(ctx->buf), 4); - span(digest->a).copy_from(as_byte_span(ctx->buf)); - std::ranges::fill(byte_span_from_ref(*ctx), 0u); /* In case it's sensitive */ -} - -std::string MD5DigestToBase16(const MD5Digest& digest) { - std::string ret; - ret.reserve(32); - for (uint8_t byte : digest.a) { - base::AppendHexEncodedByte(byte, ret, false); - } - return ret; -} - -void MD5Sum(span<const uint8_t> data, MD5Digest* digest) { - MD5Context ctx; - MD5Init(&ctx); - MD5Update(&ctx, data); - MD5Final(digest, &ctx); -} - -std::string MD5String(std::string_view str) { - MD5Digest digest; - MD5Sum(as_byte_span(str), &digest); - return MD5DigestToBase16(digest); -} - -} // namespace base
diff --git a/base/hash/md5_nacl.h b/base/hash/md5_nacl.h deleted file mode 100644 index 33d4155..0000000 --- a/base/hash/md5_nacl.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_HASH_MD5_NACL_H_ -#define BASE_HASH_MD5_NACL_H_ - -#include <stdint.h> - -#include <array> - -namespace base { - -// The output of an MD5 operation. -struct MD5Digest { - std::array<uint8_t, 16> a; -}; - -// Used for storing intermediate data during an MD5 computation. Callers -// should not access the data. -typedef char MD5Context[88]; - -} // namespace base - -#endif // BASE_HASH_MD5_NACL_H_
diff --git a/base/hash/md5_unittest.cc b/base/hash/md5_unittest.cc index 911d1aca..73590a6f 100644 --- a/base/hash/md5_unittest.cc +++ b/base/hash/md5_unittest.cc
@@ -12,7 +12,6 @@ #include "base/containers/heap_array.h" #include "base/containers/span.h" -#include "base/hash/md5_boringssl.h" #include "testing/gtest/include/gtest/gtest.h" namespace base {
diff --git a/base/hash/sha1_boringssl.cc b/base/hash/sha1.cc similarity index 96% rename from base/hash/sha1_boringssl.cc rename to base/hash/sha1.cc index 90eeac79..a6bd3c9 100644 --- a/base/hash/sha1_boringssl.cc +++ b/base/hash/sha1.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/hash/sha1_boringssl.h" +#include "base/hash/sha1.h" #include <stdint.h>
diff --git a/base/hash/sha1.h b/base/hash/sha1.h index 2158b64..edb521aa 100644 --- a/base/hash/sha1.h +++ b/base/hash/sha1.h
@@ -6,6 +6,7 @@ #define BASE_HASH_SHA1_H_ #include <stddef.h> +#include <stdint.h> #include <array> #include <string> @@ -15,14 +16,14 @@ #include "base/compiler_specific.h" #include "base/containers/span.h" #include "build/build_config.h" -#if BUILDFLAG(IS_NACL) -#include "base/hash/sha1_nacl.h" -#else -#include "base/hash/sha1_boringssl.h" -#endif +#include "third_party/boringssl/src/include/openssl/sha.h" namespace base { +// Used for storing intermediate data during an SHA1 computation. Callers +// should not access the data. +using SHA1Context = SHA_CTX; + enum { kSHA1Length = 20 }; // Length in bytes of a SHA-1 hash. // The output of an SHA-1 operation.
diff --git a/base/hash/sha1_boringssl.h b/base/hash/sha1_boringssl.h deleted file mode 100644 index 7fe64949..0000000 --- a/base/hash/sha1_boringssl.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_HASH_SHA1_BORINGSSL_H_ -#define BASE_HASH_SHA1_BORINGSSL_H_ - -#include <stdint.h> - -#include "third_party/boringssl/src/include/openssl/sha.h" - -namespace base { -// Used for storing intermediate data during an SHA1 computation. Callers -// should not access the data. -using SHA1Context = SHA_CTX; -} // namespace base - -#endif // BASE_HASH_SHA1_BORINGSSL_H_
diff --git a/base/hash/sha1_nacl.cc b/base/hash/sha1_nacl.cc deleted file mode 100644 index 669f81a..0000000 --- a/base/hash/sha1_nacl.cc +++ /dev/null
@@ -1,203 +0,0 @@ -// Copyright 2011 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/hash/sha1.h" - -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include <string_view> - -#include "base/numerics/byte_conversions.h" -#include "base/strings/string_view_util.h" - -namespace base { -// Implementation of SHA-1. Only handles data in byte-sized blocks, -// which simplifies the code a fair bit. - -// Identifier names follow notation in FIPS PUB 180-3, where you'll -// also find a description of the algorithm: -// http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf - -// Usage example: -// -// SecureHashAlgorithm sha; -// while(there is data to hash) -// sha.Update(moredata, size of data); -// sha.Final(); -// memcpy(somewhere, sha.Digest(), 20); -// -// to reuse the instance of sha, call sha.Init(); - -static inline uint32_t f(uint32_t t, uint32_t B, uint32_t C, uint32_t D) { - if (t < 20) { - return (B & C) | ((~B) & D); - } - if (t < 40) { - return B ^ C ^ D; - } - if (t < 60) { - return (B & C) | (B & D) | (C & D); - } - return B ^ C ^ D; -} - -static inline uint32_t S(uint32_t n, uint32_t X) { - return (X << n) | (X >> (32 - n)); -} - -static inline uint32_t K(uint32_t t) { - if (t < 20) { - return 0x5a827999; - } - if (t < 40) { - return 0x6ed9eba1; - } - if (t < 60) { - return 0x8f1bbcdc; - } - return 0xca62c1d6; -} - -void SHA1Context::Init() { - A = 0; - B = 0; - C = 0; - D = 0; - E = 0; - cursor = 0; - l = 0; - H[0] = 0x67452301; - H[1] = 0xefcdab89; - H[2] = 0x98badcfe; - H[3] = 0x10325476; - H[4] = 0xc3d2e1f0; -} - -void SHA1Context::Update(const void* data, size_t nbytes) { - const uint8_t* d = reinterpret_cast<const uint8_t*>(data); - while (nbytes--) { - M[cursor++] = *d++; - if (cursor >= 64) { - Process(); - } - l += 8; - } -} - -void SHA1Context::Final() { - Pad(); - Process(); - - for (auto& t : H) { - t = ByteSwap(t); - } -} - -const unsigned char* SHA1Context::GetDigest() const { - return reinterpret_cast<const unsigned char*>(H); -} - -void SHA1Context::Pad() { - M[cursor++] = 0x80; - - if (cursor > 64 - 8) { - // pad out to next block - while (cursor < 64) { - M[cursor++] = 0; - } - - Process(); - } - - while (cursor < 64 - 8) { - M[cursor++] = 0; - } - - M[cursor++] = (l >> 56) & 0xff; - M[cursor++] = (l >> 48) & 0xff; - M[cursor++] = (l >> 40) & 0xff; - M[cursor++] = (l >> 32) & 0xff; - M[cursor++] = (l >> 24) & 0xff; - M[cursor++] = (l >> 16) & 0xff; - M[cursor++] = (l >> 8) & 0xff; - M[cursor++] = l & 0xff; -} - -void SHA1Context::Process() { - uint32_t t; - - // Each a...e corresponds to a section in the FIPS 180-3 algorithm. - - // a. - // - // W and M are in a union, so no need to memcpy. - // memcpy(W, M, sizeof(M)); - for (t = 0; t < 16; ++t) { - W[t] = ByteSwap(W[t]); - } - - // b. - for (t = 16; t < 80; ++t) { - W[t] = S(1, W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]); - } - - // c. - A = H[0]; - B = H[1]; - C = H[2]; - D = H[3]; - E = H[4]; - - // d. - for (t = 0; t < 80; ++t) { - uint32_t TEMP = S(5, A) + f(t, B, C, D) + E + W[t] + K(t); - E = D; - D = C; - C = S(30, B); - B = A; - A = TEMP; - } - - // e. - H[0] += A; - H[1] += B; - H[2] += C; - H[3] += D; - H[4] += E; - - cursor = 0; -} - -// These functions allow streaming SHA-1 operations. -void SHA1Init(SHA1Context& context) { - context.Init(); -} - -void SHA1Update(std::string_view data, SHA1Context& context) { - context.Update(data.data(), data.size()); -} - -void SHA1Final(SHA1Context& context, SHA1Digest& digest) { - context.Final(); - memcpy(digest.data(), context.GetDigest(), kSHA1Length); -} - -SHA1Digest SHA1Hash(span<const uint8_t> data) { - SHA1Context context; - context.Init(); - context.Update(data.data(), data.size()); - context.Final(); - - SHA1Digest digest; - memcpy(digest.data(), context.GetDigest(), kSHA1Length); - return digest; -} - -std::string SHA1HashString(std::string_view str) { - return std::string(as_string_view(SHA1Hash(base::as_byte_span(str)))); -} - -} // namespace base
diff --git a/base/hash/sha1_nacl.h b/base/hash/sha1_nacl.h deleted file mode 100644 index fcb4845..0000000 --- a/base/hash/sha1_nacl.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_HASH_SHA1_NACL_H_ -#define BASE_HASH_SHA1_NACL_H_ - -#include <stdint.h> - -namespace base { - -// Used for storing intermediate data during an SHA1 computation. Callers -// should not access the data. -class SHA1Context { - public: - void Init(); - void Update(const void* data, size_t nbytes); - void Final(); - const unsigned char* GetDigest() const; - - private: - void Pad(); - void Process(); - - uint32_t A, B, C, D, E; - - uint32_t H[5]; - - union { - uint32_t W[80]; - uint8_t M[64]; - }; - - uint32_t cursor; - uint64_t l; -}; - -} // namespace base - -#endif // BASE_HASH_SHA1_NACL_H_
diff --git a/base/hash/sha1_unittest.cc b/base/hash/sha1_unittest.cc index 06385f3..7146ff75 100644 --- a/base/hash/sha1_unittest.cc +++ b/base/hash/sha1_unittest.cc
@@ -10,7 +10,6 @@ #include <string> #include "base/containers/span.h" -#include "base/hash/sha1_boringssl.h" #include "testing/gtest/include/gtest/gtest.h" TEST(SHA1Test, Test1) {
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc deleted file mode 100644 index 0873aa1..0000000 --- a/base/json/json_parser.cc +++ /dev/null
@@ -1,872 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/json/json_parser.h" - -#include <algorithm> -#include <cmath> -#include <iterator> -#include <memory> -#include <string_view> -#include <utility> -#include <vector> - -#include "base/check_op.h" -#include "base/compiler_specific.h" -#include "base/feature_list.h" -#include "base/features.h" -#include "base/json/json_reader.h" -#include "base/notreached.h" -#include "base/numerics/safe_conversions.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversion_utils.h" -#include "base/strings/utf_string_conversions.h" -#include "base/third_party/icu/icu_utf.h" -#include "base/types/pass_key.h" - -namespace base::internal { - -namespace { - -// Values 1000 and above are used by JSONFileValueSerializer::JsonFileError. -static_assert(JSONParser::JSON_PARSE_ERROR_COUNT < 1000, - "JSONParser error out of bounds"); - -std::string ErrorCodeToString(JSONParser::JsonParseError error_code) { - switch (error_code) { - case JSONParser::JSON_NO_ERROR: - return std::string(); - case JSONParser::JSON_SYNTAX_ERROR: - return JSONParser::kSyntaxError; - case JSONParser::JSON_INVALID_ESCAPE: - return JSONParser::kInvalidEscape; - case JSONParser::JSON_UNEXPECTED_TOKEN: - return JSONParser::kUnexpectedToken; - case JSONParser::JSON_TRAILING_COMMA: - return JSONParser::kTrailingComma; - case JSONParser::JSON_TOO_MUCH_NESTING: - return JSONParser::kTooMuchNesting; - case JSONParser::JSON_UNEXPECTED_DATA_AFTER_ROOT: - return JSONParser::kUnexpectedDataAfterRoot; - case JSONParser::JSON_UNSUPPORTED_ENCODING: - return JSONParser::kUnsupportedEncoding; - case JSONParser::JSON_UNQUOTED_DICTIONARY_KEY: - return JSONParser::kUnquotedDictionaryKey; - case JSONParser::JSON_UNREPRESENTABLE_NUMBER: - return JSONParser::kUnrepresentableNumber; - case JSONParser::JSON_PARSE_ERROR_COUNT: - NOTREACHED(); - } - NOTREACHED(); -} - -const int32_t kExtendedASCIIStart = 0x80; -constexpr base_icu::UChar32 kUnicodeReplacementPoint = 0xFFFD; - -// UnprefixedHexStringToInt acts like |HexStringToInt|, but enforces that the -// input consists purely of hex digits. I.e. no "0x" nor "OX" prefix is -// permitted. -bool UnprefixedHexStringToInt(std::string_view input, int* output) { - for (char i : input) { - if (!IsHexDigit(i)) { - return false; - } - } - return HexStringToInt(input, output); -} - -} // namespace - -// This is U+FFFD. -const char kUnicodeReplacementString[] = "\xEF\xBF\xBD"; - -const char JSONParser::kSyntaxError[] = "Syntax error."; -const char JSONParser::kInvalidEscape[] = "Invalid escape sequence."; -const char JSONParser::kUnexpectedToken[] = "Unexpected token."; -const char JSONParser::kTrailingComma[] = "Trailing comma not allowed."; -const char JSONParser::kTooMuchNesting[] = "Too much nesting."; -const char JSONParser::kUnexpectedDataAfterRoot[] = - "Unexpected data after root element."; -const char JSONParser::kUnsupportedEncoding[] = - "Unsupported encoding. JSON must be UTF-8."; -const char JSONParser::kUnquotedDictionaryKey[] = - "Dictionary keys must be quoted."; -const char JSONParser::kUnrepresentableNumber[] = - "Number cannot be represented."; - -JSONParser::JSONParser(int options, size_t max_depth) - : options_(options), - max_depth_(max_depth), - index_(0), - stack_depth_(0), - line_number_(0), - index_last_line_(0), - error_code_(JSON_NO_ERROR), - error_line_(0), - error_column_(0) { - CHECK_LE(max_depth, kAbsoluteMaxDepth); -} - -JSONParser::~JSONParser() = default; - -std::optional<Value> JSONParser::Parse(std::string_view input) { - input_ = input; - index_ = 0; - // Line and column counting is 1-based, but |index_| is 0-based. For example, - // if input is "Aaa\nB" then 'A' and 'B' are both in column 1 (at lines 1 and - // 2) and have indexes of 0 and 4. We track the line number explicitly (the - // |line_number_| field) and the column number implicitly (the difference - // between |index_| and |index_last_line_|). In calculating that difference, - // |index_last_line_| is the index of the '\r' or '\n', not the index of the - // first byte after the '\n'. For the 'B' in "Aaa\nB", its |index_| and - // |index_last_line_| would be 4 and 3: 'B' is in column (4 - 3) = 1. We - // initialize |index_last_line_| to -1, not 0, since -1 is the (out of range) - // index of the imaginary '\n' immediately before the start of the string: - // 'A' is in column (0 - -1) = 1. - line_number_ = 1; - index_last_line_ = static_cast<size_t>(-1); - - error_code_ = JSON_NO_ERROR; - error_line_ = 0; - error_column_ = 0; - - // When the input JSON string starts with a UTF-8 Byte-Order-Mark, - // advance the start position to avoid the ParseNextToken function mis- - // treating a Unicode BOM as an invalid character and returning NULL. - ConsumeIfMatch("\xEF\xBB\xBF"); - - // Parse the first and any nested tokens. - std::optional<Value> root(ParseNextToken()); - if (!root) { - return std::nullopt; - } - - // Make sure the input stream is at an end. - if (GetNextToken() != T_END_OF_INPUT) { - ReportError(JSON_UNEXPECTED_DATA_AFTER_ROOT, 0); - return std::nullopt; - } - - return root; -} - -JSONParser::JsonParseError JSONParser::error_code() const { - return error_code_; -} - -std::string JSONParser::GetErrorMessage() const { - return FormatErrorMessage(error_line_, error_column_, - ErrorCodeToString(error_code_)); -} - -int JSONParser::error_line() const { - return error_line_; -} - -int JSONParser::error_column() const { - return error_column_; -} - -// JSONParser private ////////////////////////////////////////////////////////// - -std::optional<std::string_view> JSONParser::PeekChars(size_t count) { - if (count > input_.length() - index_) { - return std::nullopt; - } - // Using string_view::substr() was historically significantly slower - // (according to base_perftests) than constructing a substring manually. - // - // TODO(crbug.com/40284755): Is this still the case? Ideally the bounds check - // performed by substr would be deleted by the optimizer for being redundant - // with the runtime check above. However, to do so, the compiler would need - // to know `index_ <= input_.length()` is a class invariant. If we - // restructured the code so that we only stored the remaining data, that - // would avoid this, but it would prevent rewinding (the places in this file - // which look at `input_[index_ - 1]`.) - return UNSAFE_BUFFERS(std::string_view(input_.data() + index_, count)); -} - -std::optional<char> JSONParser::PeekChar() { - std::optional<std::string_view> chars = PeekChars(1); - if (chars) { - return (*chars)[0]; - } - return std::nullopt; -} - -std::optional<std::string_view> JSONParser::ConsumeChars(size_t count) { - std::optional<std::string_view> chars = PeekChars(count); - if (chars) { - index_ += count; - } - return chars; -} - -std::optional<char> JSONParser::ConsumeChar() { - std::optional<std::string_view> chars = ConsumeChars(1); - if (chars) { - return (*chars)[0]; - } - return std::nullopt; -} - -const char* JSONParser::pos() { - CHECK_LE(index_, input_.length()); - // SAFETY: Checked above. - return UNSAFE_BUFFERS(input_.data() + index_); -} - -JSONParser::Token JSONParser::GetNextToken() { - EatWhitespaceAndComments(); - - std::optional<char> c = PeekChar(); - if (!c) { - return T_END_OF_INPUT; - } - - switch (*c) { - case '{': - return T_OBJECT_BEGIN; - case '}': - return T_OBJECT_END; - case '[': - return T_ARRAY_BEGIN; - case ']': - return T_ARRAY_END; - case '"': - return T_STRING; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '-': - return T_NUMBER; - case 't': - return T_BOOL_TRUE; - case 'f': - return T_BOOL_FALSE; - case 'n': - return T_NULL; - case ',': - return T_LIST_SEPARATOR; - case ':': - return T_OBJECT_PAIR_SEPARATOR; - default: - return T_INVALID_TOKEN; - } -} - -void JSONParser::EatWhitespaceAndComments() { - while (std::optional<char> c = PeekChar()) { - switch (*c) { - case '\r': - case '\n': - index_last_line_ = index_; - // Don't increment line_number_ twice for "\r\n". - if (!(c == '\n' && index_ > 0 && input_[index_ - 1] == '\r')) { - ++line_number_; - } - [[fallthrough]]; - case ' ': - case '\t': - ConsumeChar(); - break; - case '/': - if (!EatComment()) { - return; - } - break; - default: - return; - } - } -} - -bool JSONParser::EatComment() { - std::optional<std::string_view> comment_start = PeekChars(2); - if (!comment_start) { - return false; - } - - const bool comments_allowed = options_ & JSON_ALLOW_COMMENTS; - - if (comment_start == "//") { - if (!comments_allowed) { - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return false; - } - - ConsumeChars(2); - // Single line comment, read to newline. - while (std::optional<char> c = PeekChar()) { - if (c == '\n' || c == '\r') { - return true; - } - ConsumeChar(); - } - } else if (comment_start == "/*") { - if (!comments_allowed) { - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return false; - } - - ConsumeChars(2); - char previous_char = '\0'; - // Block comment, read until end marker. - while (std::optional<char> c = PeekChar()) { - if (previous_char == '*' && c == '/') { - // EatWhitespaceAndComments will inspect pos(), which will still be on - // the last / of the comment, so advance once more (which may also be - // end of input). - ConsumeChar(); - return true; - } - previous_char = *ConsumeChar(); - } - - // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT. - } - - return false; -} - -std::optional<Value> JSONParser::ParseNextToken() { - return ParseToken(GetNextToken()); -} - -std::optional<Value> JSONParser::ParseToken(Token token) { - switch (token) { - case T_OBJECT_BEGIN: - return ConsumeDictionary(); - case T_ARRAY_BEGIN: - return ConsumeList(); - case T_STRING: - return ConsumeString(); - case T_NUMBER: - return ConsumeNumber(); - case T_BOOL_TRUE: - case T_BOOL_FALSE: - case T_NULL: - return ConsumeLiteral(); - default: - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return std::nullopt; - } -} - -std::optional<Value> JSONParser::ConsumeDictionary() { - if (ConsumeChar() != '{') { - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return std::nullopt; - } - - StackMarker depth_check(max_depth_, &stack_depth_); - if (depth_check.IsTooDeep()) { - ReportError(JSON_TOO_MUCH_NESTING, -1); - return std::nullopt; - } - - std::vector<std::pair<std::string, std::unique_ptr<Value>>> values; - - Token token = GetNextToken(); - while (token != T_OBJECT_END) { - if (token != T_STRING) { - ReportError(JSON_UNQUOTED_DICTIONARY_KEY, 0); - return std::nullopt; - } - - // First consume the key. - std::optional<std::string> key = ConsumeStringRaw(); - if (!key) { - return std::nullopt; - } - - // Read the separator. - token = GetNextToken(); - if (token != T_OBJECT_PAIR_SEPARATOR) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - - // The next token is the value. Ownership transfers to |dict|. - ConsumeChar(); - std::optional<Value> value = ParseNextToken(); - if (!value) { - // ReportError from deeper level. - return std::nullopt; - } - - values.emplace_back(std::move(*key), - std::make_unique<Value>(std::move(*value))); - - token = GetNextToken(); - if (token == T_LIST_SEPARATOR) { - ConsumeChar(); - token = GetNextToken(); - if (token == T_OBJECT_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) { - ReportError(JSON_TRAILING_COMMA, 0); - return std::nullopt; - } - } else if (token != T_OBJECT_END) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - } - - ConsumeChar(); // Closing '}'. - // Reverse |dict_storage| to keep the last of elements with the same key in - // the input. - std::ranges::reverse(values); - return Value(Value::Dict(PassKey<JSONParser>(), std::move(values))); -} - -std::optional<Value> JSONParser::ConsumeList() { - if (ConsumeChar() != '[') { - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return std::nullopt; - } - - StackMarker depth_check(max_depth_, &stack_depth_); - if (depth_check.IsTooDeep()) { - ReportError(JSON_TOO_MUCH_NESTING, -1); - return std::nullopt; - } - - Value::List list; - - Token token = GetNextToken(); - while (token != T_ARRAY_END) { - std::optional<Value> item = ParseToken(token); - if (!item) { - // ReportError from deeper level. - return std::nullopt; - } - - list.Append(std::move(*item)); - - token = GetNextToken(); - if (token == T_LIST_SEPARATOR) { - ConsumeChar(); - token = GetNextToken(); - if (token == T_ARRAY_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) { - ReportError(JSON_TRAILING_COMMA, 0); - return std::nullopt; - } - } else if (token != T_ARRAY_END) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - } - - ConsumeChar(); // Closing ']'. - - return Value(std::move(list)); -} - -std::optional<Value> JSONParser::ConsumeString() { - std::optional<std::string> string = ConsumeStringRaw(); - if (!string) { - return std::nullopt; - } - return Value(std::move(*string)); -} - -std::optional<std::string> JSONParser::ConsumeStringRaw() { - if (ConsumeChar() != '"') { - ReportError(JSON_UNEXPECTED_TOKEN, 0); - return std::nullopt; - } - - std::string string; - for (;;) { - auto [result, consumed] = ConsumeStringPart(); - switch (result) { - case StringResult::kError: - return std::nullopt; - - case StringResult::kDone: - // This is the last time we're appending, so pre-reserve the desired - // size, to prevent `+=` from overallocating. (In other cases, the - // overallocating is desirable for amortization.) In particular, - // the common case is that `string` is empty and we return in one step. - string.reserve(string.size() + consumed.size()); - string += consumed; - return std::move(string); - - case StringResult::kReplacementCharacter: - string += consumed; - string += kUnicodeReplacementString; - break; // Keep parsing. - - case StringResult::kEscape: - string += consumed; - std::optional<char> escape_char = ConsumeChar(); - if (!escape_char) { - ReportError(JSON_INVALID_ESCAPE, -1); - return std::nullopt; - } - - switch (*escape_char) { - // Allowed esape sequences: - case 'x': { // UTF-8 sequence. - // UTF-8 \x escape sequences are not allowed in the spec, but they - // are supported here for backwards-compatiblity with the old - // parser. - if (!(options_ & JSON_ALLOW_X_ESCAPES)) { - ReportError(JSON_INVALID_ESCAPE, -1); - return std::nullopt; - } - - std::optional<std::string_view> escape_sequence = ConsumeChars(2); - if (!escape_sequence) { - ReportError(JSON_INVALID_ESCAPE, -3); - return std::nullopt; - } - - int hex_digit = 0; - if (!UnprefixedHexStringToInt(*escape_sequence, &hex_digit)) { - ReportError(JSON_INVALID_ESCAPE, -3); - return std::nullopt; - } - - // A two-character hex sequence is at most 0xff and all codepoints - // up to 0xff are valid. - DCHECK_LE(hex_digit, 0xff); - DCHECK(IsValidCharacter(hex_digit)); - WriteUnicodeCharacter(hex_digit, &string); - break; - } - case 'u': { // UTF-16 sequence. - // UTF units are of the form \uXXXX. - base_icu::UChar32 code_point; - if (!DecodeUTF16(&code_point)) { - ReportError(JSON_INVALID_ESCAPE, -1); - return std::nullopt; - } - WriteUnicodeCharacter(code_point, &string); - break; - } - case '"': - string.push_back('"'); - break; - case '\\': - string.push_back('\\'); - break; - case '/': - string.push_back('/'); - break; - case 'b': - string.push_back('\b'); - break; - case 'f': - string.push_back('\f'); - break; - case 'n': - string.push_back('\n'); - break; - case 'r': - string.push_back('\r'); - break; - case 't': - string.push_back('\t'); - break; - case 'v': // Not listed as valid escape sequence in the RFC. - if (!(options_ & JSON_ALLOW_VERT_TAB)) { - ReportError(JSON_INVALID_ESCAPE, -1); - return std::nullopt; - } - string.push_back('\v'); - break; - // All other escape squences are illegal. - default: - ReportError(JSON_INVALID_ESCAPE, -1); - return std::nullopt; - } - break; // Keep parsing. - } - } -} - -std::pair<JSONParser::StringResult, std::string_view> -JSONParser::ConsumeStringPart() { - const size_t start_index = index_; - while (std::optional<char> c = PeekChar()) { - // Handle non-ASCII characters, which never trigger any special handling - // beyond needing to be valid UTF-8. ASCII characters will be handled - // separately below. - if (static_cast<unsigned char>(*c) >= kExtendedASCIIStart) { - base_icu::UChar32 next_char = 0; - size_t last_index = index_; - if (!ReadUnicodeCharacter(input_.data(), input_.length(), &index_, - &next_char)) { - if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { - ReportError(JSON_UNSUPPORTED_ENCODING, 0); - // No need to return consumed data. - return {StringResult::kError, {}}; - } - ConsumeChar(); - return {StringResult::kReplacementCharacter, - input_.substr(start_index, last_index - start_index)}; - } - - // Valid UTF-8 will be copied as-is into the output, so keep processing. - DCHECK_GE(next_char, kExtendedASCIIStart); - ConsumeChar(); - continue; - } - - if (*c == '"') { - std::string_view ret = input_.substr(start_index, index_ - start_index); - ConsumeChar(); - return {StringResult::kDone, ret}; - } - if (*c == '\\') { - std::string_view ret = input_.substr(start_index, index_ - start_index); - ConsumeChar(); - return {StringResult::kEscape, ret}; - } - - // Per Section 7, "All Unicode characters may be placed within the - // quotation marks, except for the characters that MUST be escaped: - // quotation mark, reverse solidus, and the control characters (U+0000 - // through U+001F)". - if (*c == '\n' || *c == '\r') { - if (!(options_ & JSON_ALLOW_NEWLINES_IN_STRINGS)) { - ReportError(JSON_UNSUPPORTED_ENCODING, -1); - return {StringResult::kError, {}}; // No need to return consumed data. - } - } else if (*c <= 0x1F) { - ReportError(JSON_UNSUPPORTED_ENCODING, -1); - return {StringResult::kError, {}}; // No need to return consumed data. - } - - // If this character is not an escape sequence, track any line breaks and - // keep parsing. The JSON spec forbids unescaped ASCII control characters - // within a string, including '\r' and '\n', but this implementation is more - // lenient. - if (*c == '\r' || *c == '\n') { - index_last_line_ = index_; - // Don't increment line_number_ twice for "\r\n". We are guaranteed that - // (index_ > 0) because we are consuming a string, so we must have seen an - // opening '"' quote character. - if ((*c == '\r') || (input_[index_ - 1] != '\r')) { - ++line_number_; - } - } - ConsumeChar(); - } - - ReportError(JSON_SYNTAX_ERROR, -1); - return {StringResult::kError, {}}; // No need to return consumed data. -} - -// Entry is at the first X in \uXXXX. -bool JSONParser::DecodeUTF16(base_icu::UChar32* out_code_point) { - std::optional<std::string_view> escape_sequence = ConsumeChars(4); - if (!escape_sequence) { - return false; - } - - // Consume the UTF-16 code unit, which may be a high surrogate. - int code_unit16_high = 0; - if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_high)) { - return false; - } - - // If this is a high surrogate, consume the next code unit to get the - // low surrogate. - if (CBU16_IS_SURROGATE(code_unit16_high)) { - // Make sure this is the high surrogate. - if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high)) { - if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { - return false; - } - *out_code_point = kUnicodeReplacementPoint; - return true; - } - - // Make sure that the token has more characters to consume the - // lower surrogate. - if (!ConsumeIfMatch("\\u")) { - if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { - return false; - } - *out_code_point = kUnicodeReplacementPoint; - return true; - } - - escape_sequence = ConsumeChars(4); - if (!escape_sequence) { - return false; - } - - int code_unit16_low = 0; - if (!UnprefixedHexStringToInt(*escape_sequence, &code_unit16_low)) { - return false; - } - - if (!CBU16_IS_TRAIL(code_unit16_low)) { - if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) { - return false; - } - *out_code_point = kUnicodeReplacementPoint; - return true; - } - - base_icu::UChar32 code_point = - CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low); - - *out_code_point = code_point; - } else { - // Not a surrogate. - DCHECK(CBU16_IS_SINGLE(code_unit16_high)); - - *out_code_point = code_unit16_high; - } - - return true; -} - -std::optional<Value> JSONParser::ConsumeNumber() { - const char* num_start = pos(); - const size_t start_index = index_; - size_t end_index = start_index; - - if (PeekChar() == '-') { - ConsumeChar(); - } - - if (!ReadInt(false)) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - end_index = index_; - - // The optional fraction part. - if (PeekChar() == '.') { - ConsumeChar(); - if (!ReadInt(true)) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - end_index = index_; - } - - // Optional exponent part. - std::optional<char> c = PeekChar(); - if (c == 'e' || c == 'E') { - ConsumeChar(); - if (PeekChar() == '-' || PeekChar() == '+') { - ConsumeChar(); - } - if (!ReadInt(true)) { - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; - } - end_index = index_; - } - - std::string_view num_string(num_start, end_index - start_index); - - int num_int; - if (StringToInt(num_string, &num_int)) { - // StringToInt will treat `-0` as zero, losing the significance of the - // negation. - if (num_int == 0 && num_string.starts_with('-')) { - return Value(-0.0); - } - return Value(num_int); - } - - double num_double; - if (StringToDouble(num_string, &num_double) && std::isfinite(num_double)) { - return Value(num_double); - } - - ReportError(JSON_UNREPRESENTABLE_NUMBER, 0); - return std::nullopt; -} - -bool JSONParser::ReadInt(bool allow_leading_zeros) { - size_t len = 0; - char first = 0; - - while (std::optional<char> c = PeekChar()) { - if (!IsAsciiDigit(*c)) { - break; - } - - if (len == 0) { - first = *c; - } - - ++len; - ConsumeChar(); - } - - if (len == 0) { - return false; - } - - if (!allow_leading_zeros && len > 1 && first == '0') { - return false; - } - - return true; -} - -std::optional<Value> JSONParser::ConsumeLiteral() { - if (ConsumeIfMatch("true")) { - return Value(true); - } - if (ConsumeIfMatch("false")) { - return Value(false); - } - if (ConsumeIfMatch("null")) { - return Value(Value::Type::NONE); - } - ReportError(JSON_SYNTAX_ERROR, 0); - return std::nullopt; -} - -bool JSONParser::ConsumeIfMatch(std::string_view match) { - if (match == PeekChars(match.size())) { - ConsumeChars(match.size()); - return true; - } - return false; -} - -void JSONParser::ReportError(JsonParseError code, int column_adjust) { - error_code_ = code; - error_line_ = line_number_; - error_column_ = static_cast<int>(index_ - index_last_line_) + column_adjust; - - // For a final blank line ('\n' and then EOF), a negative column_adjust may - // put us below 1, which doesn't really make sense for 1-based columns. - if (error_column_ < 1) { - error_column_ = 1; - } -} - -// static -std::string JSONParser::FormatErrorMessage(int line, - int column, - const std::string& description) { - if (line || column) { - return StringPrintf("Line: %i, column: %i, %s", line, column, - description.c_str()); - } - return description; -} - -} // namespace base::internal
diff --git a/base/json/json_parser.h b/base/json/json_parser.h deleted file mode 100644 index 92e0586..0000000 --- a/base/json/json_parser.h +++ /dev/null
@@ -1,269 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_JSON_JSON_PARSER_H_ -#define BASE_JSON_JSON_PARSER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <optional> -#include <string> -#include <string_view> -#include <utility> - -#include "base/base_export.h" -#include "base/compiler_specific.h" -#include "base/gtest_prod_util.h" -#include "base/json/json_common.h" -#include "base/third_party/icu/icu_utf.h" -#include "base/values.h" - -namespace base { - -class Value; - -namespace internal { - -class JSONParserTest; - -// The implementation behind the JSONReader interface. This class is not meant -// to be used directly; it encapsulates logic that need not be exposed publicly. -// -// This parser guarantees O(n) time through the input string. Iteration happens -// on the byte level, with the functions ConsumeChars() and ConsumeChar(). The -// conversion from byte to JSON token happens without advancing the parser in -// GetNextToken/ParseToken, that is tokenization operates on the current parser -// position without advancing. -// -// Built on top of these are a family of Consume functions that iterate -// internally. Invariant: on entry of a Consume function, the parser is wound -// to the first byte of a valid JSON token. On exit, it is on the first byte -// after the token that was just consumed, which would likely be the first byte -// of the next token. -class BASE_EXPORT JSONParser { - public: - // Error codes during parsing. - enum JsonParseError { - JSON_NO_ERROR = base::ValueDeserializer::kErrorCodeNoError, - JSON_SYNTAX_ERROR = base::ValueDeserializer::kErrorCodeInvalidFormat, - JSON_INVALID_ESCAPE, - JSON_UNEXPECTED_TOKEN, - JSON_TRAILING_COMMA, - JSON_TOO_MUCH_NESTING, - JSON_UNEXPECTED_DATA_AFTER_ROOT, - JSON_UNSUPPORTED_ENCODING, - JSON_UNQUOTED_DICTIONARY_KEY, - JSON_UNREPRESENTABLE_NUMBER, - JSON_PARSE_ERROR_COUNT - }; - - // String versions of parse error codes. - static const char kSyntaxError[]; - static const char kInvalidEscape[]; - static const char kUnexpectedToken[]; - static const char kTrailingComma[]; - static const char kTooMuchNesting[]; - static const char kUnexpectedDataAfterRoot[]; - static const char kUnsupportedEncoding[]; - static const char kUnquotedDictionaryKey[]; - static const char kUnrepresentableNumber[]; - - explicit JSONParser(int options, size_t max_depth = kAbsoluteMaxDepth); - - JSONParser(const JSONParser&) = delete; - JSONParser& operator=(const JSONParser&) = delete; - - ~JSONParser(); - - // Parses the input string according to the set options and returns the - // result as a Value. - // Wrap this in base::FooValue::From() to check the Value is of type Foo and - // convert to a FooValue at the same time. - std::optional<Value> Parse(std::string_view input); - - // Returns the error code. - JsonParseError error_code() const; - - // Returns the human-friendly error message. - std::string GetErrorMessage() const; - - // Returns the error line number if parse error happened. Otherwise always - // returns 0. - int error_line() const; - - // Returns the error column number if parse error happened. Otherwise always - // returns 0. - int error_column() const; - - private: - enum Token { - T_OBJECT_BEGIN, // { - T_OBJECT_END, // } - T_ARRAY_BEGIN, // [ - T_ARRAY_END, // ] - T_STRING, - T_NUMBER, - T_BOOL_TRUE, // true - T_BOOL_FALSE, // false - T_NULL, // null - T_LIST_SEPARATOR, // , - T_OBJECT_PAIR_SEPARATOR, // : - T_END_OF_INPUT, - T_INVALID_TOKEN, - }; - - // Returns the next |count| bytes of the input stream, or nullopt if fewer - // than |count| bytes remain. - std::optional<std::string_view> PeekChars(size_t count); - - // Calls PeekChars() with a |count| of 1. - std::optional<char> PeekChar(); - - // Returns the next |count| bytes of the input stream, or nullopt if fewer - // than |count| bytes remain, and advances the parser position by |count|. - std::optional<std::string_view> ConsumeChars(size_t count); - - // Calls ConsumeChars() with a |count| of 1. - std::optional<char> ConsumeChar(); - - // Returns a pointer to the current character position. - const char* pos(); - - // Skips over whitespace and comments to find the next token in the stream. - // This does not advance the parser for non-whitespace or comment chars. - Token GetNextToken(); - - // Consumes whitespace characters and comments until the next non-that is - // encountered. - void EatWhitespaceAndComments(); - // Helper function that consumes a comment, assuming that the parser is - // currently wound to a '/'. - bool EatComment(); - - // Calls GetNextToken() and then ParseToken(). - std::optional<Value> ParseNextToken(); - - // Takes a token that represents the start of a Value ("a structural token" - // in RFC terms) and consumes it, returning the result as a Value. - std::optional<Value> ParseToken(Token token); - - // Assuming that the parser is currently wound to '{', this parses a JSON - // object into a Value. - std::optional<Value> ConsumeDictionary(); - - // Assuming that the parser is wound to '[', this parses a JSON list into a - // Value. - std::optional<Value> ConsumeList(); - - // Calls through ConsumeStringRaw and wraps it in a value. - std::optional<Value> ConsumeString(); - - // Assuming that the parser is wound to a double quote, this parses a string, - // decoding any escape sequences and validating UTF-8. Returns the string on - // success or std::nullopt on error, with error information set. - std::optional<std::string> ConsumeStringRaw(); - - enum class StringResult { - // Parsing stopped because of invalid input. Error information has been set. - // The caller should return failure. - kError, - // Parsing stopped because the string is finished. The parser is wound to - // just paste the closing quote. The caller should stop parsing the string. - kDone, - // Parsing stopped because of invalid Unicode which should be replaced with - // a replacement character. The parser is wound to just past the input that - // should be a replacement character. The caller should add a replacement - // character and continue parsing. - kReplacementCharacter, - // Parsing stopped because of an escape sequence. The parser is wound to - // just past the backslash. The caller should consume the escape sequence - // and continue parsing. - kEscape, - }; - - // Consumes the portion of a JavaScript string which may be copied to the - // input with no conversions, stopping at one of the events above. Returns the - // reason parsing stopped and the data that was consumed. This should be - // called in a loop, handling all the cases above until reaching kDone. - std::pair<StringResult, std::string_view> ConsumeStringPart(); - - // Helper function for ConsumeStringRaw() that consumes the next four or 10 - // bytes (parser is wound to the first character of a HEX sequence, with the - // potential for consuming another \uXXXX for a surrogate). Returns true on - // success and places the code point |out_code_point|, and false on failure. - bool DecodeUTF16(base_icu::UChar32* out_code_point); - - // Assuming that the parser is wound to the start of a valid JSON number, - // this parses and converts it to either an int or double value. - std::optional<Value> ConsumeNumber(); - // Helper that reads characters that are ints. Returns true if a number was - // read and false on error. - bool ReadInt(bool allow_leading_zeros); - - // Consumes the literal values of |true|, |false|, and |null|, assuming the - // parser is wound to the first character of any of those. - std::optional<Value> ConsumeLiteral(); - - // Helper function that returns true if the byte squence |match| can be - // consumed at the current parser position. Returns false if there are fewer - // than |match|-length bytes or if the sequence does not match, and the - // parser state is unchanged. - bool ConsumeIfMatch(std::string_view match); - - // Sets the error information to |code| at the current column, based on - // |index_| and |index_last_line_|, with an optional positive/negative - // adjustment by |column_adjust|. - void ReportError(JsonParseError code, int column_adjust); - - // Given the line and column number of an error, formats one of the error - // message contants from json_reader.h for human display. - static std::string FormatErrorMessage(int line, - int column, - const std::string& description); - - // base::JSONParserOptions that control parsing. - const int options_; - - // Maximum depth to parse. - const size_t max_depth_; - - // The input stream being parsed. Note: Not guaranteed to NUL-terminated. - std::string_view input_; - - // The index in the input stream to which the parser is wound. - size_t index_; - - // The number of times the parser has recursed (current stack depth). - size_t stack_depth_; - - // The line number that the parser is at currently. - int line_number_; - - // The last value of |index_| on the previous line. - size_t index_last_line_; - - // Error information. - JsonParseError error_code_; - int error_line_; - int error_column_; - - friend class JSONParserTest; - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, NextChar); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeDictionary); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeList); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeString); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeLiterals); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ConsumeNumbers); - FRIEND_TEST_ALL_PREFIXES(JSONParserTest, ErrorMessages); -}; - -// Used when decoding and an invalid utf-8 sequence is encountered. -BASE_EXPORT extern const char kUnicodeReplacementString[]; - -} // namespace internal -} // namespace base - -#endif // BASE_JSON_JSON_PARSER_H_
diff --git a/base/json/json_parser_unittest.cc b/base/json/json_parser_unittest.cc deleted file mode 100644 index bd4a1c1..0000000 --- a/base/json/json_parser_unittest.cc +++ /dev/null
@@ -1,341 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/json/json_parser.h" - -#include <stddef.h> - -#include <memory> -#include <optional> - -#include "base/json/json_reader.h" -#include "base/memory/ptr_util.h" -#include "base/values.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base::internal { - -class JSONParserTest : public testing::Test { - public: - JSONParser* NewTestParser(const std::string& input, - int options = JSON_PARSE_RFC) { - JSONParser* parser = new JSONParser(options); - parser->input_ = input; - parser->index_ = 0; - return parser; - } - - void TestLastThree(JSONParser* parser) { - EXPECT_EQ(',', *parser->PeekChar()); - parser->ConsumeChar(); - EXPECT_EQ('|', *parser->PeekChar()); - parser->ConsumeChar(); - EXPECT_EQ('\0', *parser->pos()); - EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length()); - } -}; - -TEST_F(JSONParserTest, NextChar) { - std::string input("Hello world"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - - EXPECT_EQ('H', *parser->pos()); - for (size_t i = 1; i < input.length(); ++i) { - parser->ConsumeChar(); - EXPECT_EQ(input[i], *parser->PeekChar()); - } - parser->ConsumeChar(); - EXPECT_EQ('\0', *parser->pos()); - EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length()); -} - -TEST_F(JSONParserTest, ConsumeString) { - std::string input("\"test\",|"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - std::optional<Value> value(parser->ConsumeString()); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_string()); - EXPECT_EQ("test", value->GetString()); -} - -TEST_F(JSONParserTest, ConsumeList) { - std::string input("[true, false],|"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - std::optional<Value> value(parser->ConsumeList()); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - Value::List* list = value->GetIfList(); - ASSERT_TRUE(list); - EXPECT_EQ(2u, list->size()); -} - -TEST_F(JSONParserTest, ConsumeDictionary) { - std::string input("{\"abc\":\"def\"},|"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - std::optional<Value> value(parser->ConsumeDictionary()); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - const Value::Dict* value_dict = value->GetIfDict(); - ASSERT_TRUE(value_dict); - const std::string* str = value_dict->FindString("abc"); - ASSERT_TRUE(str); - EXPECT_EQ("def", *str); -} - -TEST_F(JSONParserTest, ConsumeLiterals) { - // Literal |true|. - std::string input("true,|"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - std::optional<Value> value(parser->ConsumeLiteral()); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_bool()); - EXPECT_TRUE(value->GetBool()); - - // Literal |false|. - input = "false,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeLiteral(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_bool()); - EXPECT_FALSE(value->GetBool()); - - // Literal |null|. - input = "null,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeLiteral(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - EXPECT_TRUE(value->is_none()); -} - -TEST_F(JSONParserTest, ConsumeNumbers) { - // Integer. - std::string input("1234,|"); - std::unique_ptr<JSONParser> parser(NewTestParser(input)); - std::optional<Value> value(parser->ConsumeNumber()); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_int()); - EXPECT_EQ(1234, value->GetInt()); - - // Negative integer. - input = "-1234,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_int()); - EXPECT_EQ(-1234, value->GetInt()); - - // Negative zero integer. - input = "-0,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(-0.0, value->GetDouble()); - - // Double. - input = "12.34,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(12.34, value->GetDouble()); - - // Negative zero double. - input = "-0.0,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(-0.0, value->GetDouble()); - - // Scientific. - input = "42e3,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(42000, value->GetDouble()); - - // Negative scientific. - input = "314159e-5,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(3.14159, value->GetDouble()); - - // Positive scientific. - input = "0.42e+3,|"; - parser.reset(NewTestParser(input)); - value = parser->ConsumeNumber(); - EXPECT_EQ(',', *parser->pos()); - - TestLastThree(parser.get()); - - ASSERT_TRUE(value); - ASSERT_TRUE(value->is_double()); - EXPECT_EQ(420, value->GetDouble()); -} - -TEST_F(JSONParserTest, ErrorMessages) { - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("[42]"); - EXPECT_TRUE(value); - EXPECT_TRUE(parser.GetErrorMessage().empty()); - EXPECT_EQ(0, parser.error_code()); - } - - // Test each of the error conditions - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("{},{}"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage( - 1, 3, JSONParser::kUnexpectedDataAfterRoot), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_UNEXPECTED_DATA_AFTER_ROOT, parser.error_code()); - } - - { - std::string nested_json; - for (int i = 0; i < 201; ++i) { - nested_json.insert(nested_json.begin(), '['); - nested_json.append(1, ']'); - } - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse(nested_json); - EXPECT_FALSE(value); - EXPECT_EQ( - JSONParser::FormatErrorMessage(1, 200, JSONParser::kTooMuchNesting), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_TOO_MUCH_NESTING, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("[1,]"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 4, JSONParser::kTrailingComma), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_TRAILING_COMMA, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("{foo:\"bar\"}"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage( - 1, 2, JSONParser::kUnquotedDictionaryKey), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_UNQUOTED_DICTIONARY_KEY, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("{\"foo\":\"bar\",}"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 14, JSONParser::kTrailingComma), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_TRAILING_COMMA, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("[nu]"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2, JSONParser::kSyntaxError), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_SYNTAX_ERROR, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC | JSON_ALLOW_X_ESCAPES); - std::optional<Value> value = parser.Parse("[\"xxx\\xq\"]"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("[\"xxx\\uq\"]"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("[\"xxx\\q\"]"); - EXPECT_FALSE(value); - EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONParser::kInvalidEscape), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_INVALID_ESCAPE, parser.error_code()); - } - - { - JSONParser parser(JSON_PARSE_RFC); - std::optional<Value> value = parser.Parse("\"abc\ndef\""); - EXPECT_FALSE(value); - EXPECT_EQ( - JSONParser::FormatErrorMessage(1, 4, JSONParser::kUnsupportedEncoding), - parser.GetErrorMessage()); - EXPECT_EQ(JSONParser::JSON_UNSUPPORTED_ENCODING, parser.error_code()); - } -} - -} // namespace base::internal
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index eb57cc9..664b729 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc
@@ -12,18 +12,9 @@ #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "build/build_config.h" - -#if BUILDFLAG(IS_NACL) -#include "base/json/json_parser.h" -#else #include "base/strings/string_view_rust.h" #include "third_party/rust/serde_json_lenient/v0_2/wrapper/functions.h" #include "third_party/rust/serde_json_lenient/v0_2/wrapper/lib.rs.h" -#endif - -// TODO(crbug.com/40811643): Move the C++ parser into components/nacl to just -// run in-process there. Don't compile base::JSONReader on NaCL at all. -#if !BUILDFLAG(IS_NACL) namespace { const char kSecurityJsonParsingTime[] = "Security.JSONParser.ParsingTime"; @@ -131,8 +122,6 @@ } // namespace } // namespace serde_json_lenient -#endif // !BUILDFLAG(IS_NACL) - namespace base { std::string JSONReader::Error::ToString() const { @@ -144,10 +133,6 @@ std::optional<Value> JSONReader::Read(std::string_view json, int options, size_t max_depth) { -#if BUILDFLAG(IS_NACL) - internal::JSONParser parser(options, max_depth); - return parser.Parse(json); -#else // BUILDFLAG(IS_NACL) SCOPED_UMA_HISTOGRAM_TIMER_MICROS(kSecurityJsonParsingTime); JSONReader::Result result = @@ -156,7 +141,6 @@ return std::nullopt; } return std::move(*result); -#endif // BUILDFLAG(IS_NACL) } // static @@ -185,23 +169,9 @@ JSONReader::Result JSONReader::ReadAndReturnValueWithError( std::string_view json, int options) { -#if BUILDFLAG(IS_NACL) - internal::JSONParser parser(options); - auto value = parser.Parse(json); - if (!value) { - Error error; - error.message = parser.GetErrorMessage(); - error.line = parser.error_line(); - error.column = parser.error_column(); - return base::unexpected(std::move(error)); - } - - return std::move(*value); -#else // BUILDFLAG(IS_NACL) SCOPED_UMA_HISTOGRAM_TIMER_MICROS(kSecurityJsonParsingTime); return serde_json_lenient::DecodeJSONInRust(json, options, internal::kAbsoluteMaxDepth); -#endif // BUILDFLAG(IS_NACL) } } // namespace base
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc index 2dd5aaa..8d898db 100644 --- a/base/memory/discardable_shared_memory.cc +++ b/base/memory/discardable_shared_memory.cc
@@ -24,7 +24,7 @@ #include "partition_alloc/page_allocator.h" // nogncheck #endif -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_POSIX) // For madvise() which is available on all POSIX compatible systems. #include <sys/mman.h> #endif @@ -425,7 +425,7 @@ // Note: this memory will not be accessed again. The segment will be // freed asynchronously at a later time, so just do the best // immediately. -#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_POSIX) // Linux and Android provide MADV_REMOVE which is preferred as it has a // behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs), // provide MADV_FREE which has the same result but memory is purged lazily.
diff --git a/base/memory/page_size_nacl.cc b/base/memory/page_size_nacl.cc deleted file mode 100644 index 02ebc271..0000000 --- a/base/memory/page_size_nacl.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <stddef.h> -#include <unistd.h> - -#include "base/process/process_metrics.h" - -namespace base { - -size_t GetPageSize() { - return static_cast<size_t>(getpagesize()); -} - -} // namespace base
diff --git a/base/memory/platform_shared_memory_region_posix.cc b/base/memory/platform_shared_memory_region_posix.cc index 6baaa72..37b6c29 100644 --- a/base/memory/platform_shared_memory_region_posix.cc +++ b/base/memory/platform_shared_memory_region_posix.cc
@@ -36,7 +36,6 @@ using ScopedPathUnlinker = ScopedGeneric<const FilePath*, ScopedPathUnlinkerTraits>; -#if !BUILDFLAG(IS_NACL) enum class FDAccessModeError { kFcntlFailed, kMismatch, @@ -57,7 +56,6 @@ return std::nullopt; } -#endif // !BUILDFLAG(IS_NACL) } // namespace @@ -191,10 +189,6 @@ bool executable #endif ) { -#if BUILDFLAG(IS_NACL) - // Untrusted code can't create descriptors or handles. - return {}; -#else if (size == 0) { return {}; } @@ -283,7 +277,6 @@ return PlatformSharedMemoryRegion( {ScopedFD(shm_file.TakePlatformFile()), std::move(readonly_fd)}, mode, size, UnguessableToken::Create()); -#endif // !BUILDFLAG(IS_NACL) } expected<void, PlatformSharedMemoryRegion::TakeError> @@ -291,7 +284,6 @@ PlatformSharedMemoryHandle handle, Mode mode, size_t size) { -#if !BUILDFLAG(IS_NACL) if (auto result = CheckFDAccessMode( handle.fd, mode == Mode::kReadOnly ? O_RDONLY : O_RDWR); result.has_value()) { @@ -324,12 +316,6 @@ } return ok(); -#else - // fcntl(_, F_GETFL) is not implemented on NaCl. - // We also cannot try to mmap() a region as writable and look at the return - // status because the plugin process crashes if system mmap() fails. - return ok(); -#endif // !BUILDFLAG(IS_NACL) } PlatformSharedMemoryRegion::PlatformSharedMemoryRegion(
diff --git a/base/memory/shared_memory_mapping_unittest.cc b/base/memory/shared_memory_mapping_unittest.cc index d8ead663..3666b8f 100644 --- a/base/memory/shared_memory_mapping_unittest.cc +++ b/base/memory/shared_memory_mapping_unittest.cc
@@ -277,9 +277,7 @@ // Nothing interesting to test if the address space isn't 64 bits, since // there's no real limit enforced on 32 bits other than complete address // space exhaustion. - // Also exclude NaCl since pointers are 32 bits on all architectures: - // https://bugs.chromium.org/p/nativeclient/issues/detail?id=1162 -#if defined(ARCH_CPU_64_BITS) && !BUILDFLAG(IS_NACL) +#if defined(ARCH_CPU_64_BITS) auto region = WritableSharedMemoryRegion::Create(1024 * 1024 * 1024); ASSERT_TRUE(region.IsValid()); // The limit is 32GB of mappings on 64-bit platforms, so the final mapping
diff --git a/base/memory/shared_memory_security_policy.cc b/base/memory/shared_memory_security_policy.cc index 8add35a3..c03dba3 100644 --- a/base/memory/shared_memory_security_policy.cc +++ b/base/memory/shared_memory_security_policy.cc
@@ -18,9 +18,7 @@ namespace { -// Note: pointers are 32 bits on all architectures in NaCl. See -// https://bugs.chromium.org/p/nativeclient/issues/detail?id=1162 -#if defined(ARCH_CPU_32_BITS) || BUILDFLAG(IS_NACL) +#if defined(ARCH_CPU_32_BITS) // No effective limit on 32-bit, since there simply isn't enough address space // for ASLR to be particularly effective. constexpr size_t kTotalMappedSizeLimit = std::numeric_limits<size_t>::max();
diff --git a/base/notreached.h b/base/notreached.h index d8f5b9d..c6b94654 100644 --- a/base/notreached.h +++ b/base/notreached.h
@@ -10,10 +10,6 @@ #include "base/compiler_specific.h" #include "base/dcheck_is_on.h" -// TODO(crbug.com/41493641): Remove once NOTIMPLEMENTED() call sites include -// base/notimplemented.h. -#include "base/notimplemented.h" - namespace logging { #if CHECK_WILL_STREAM()
diff --git a/base/os_compat_nacl.cc b/base/os_compat_nacl.cc deleted file mode 100644 index 1f169e8..0000000 --- a/base/os_compat_nacl.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/os_compat_nacl.h" - -#include <stdlib.h> -#include <time.h> - -#if !defined(__GLIBC__) - -extern "C" { -// Native Client has no timegm(). -time_t timegm(struct tm* tm) { - time_t ret; - char* tz; - tz = getenv("TZ"); - setenv("TZ", "", 1); - tzset(); - ret = mktime(tm); - if (tz) { - setenv("TZ", tz, 1); - } else { - unsetenv("TZ"); - } - tzset(); - return ret; -} -} // extern "C" - -#endif // !defined (__GLIBC__)
diff --git a/base/os_compat_nacl.h b/base/os_compat_nacl.h deleted file mode 100644 index b033c1e3..0000000 --- a/base/os_compat_nacl.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_OS_COMPAT_NACL_H_ -#define BASE_OS_COMPAT_NACL_H_ - -#include <sys/types.h> - -#if !defined(__GLIBC__) -// NaCl has no timegm(). -extern "C" time_t timegm(struct tm* const t); -#endif // !defined (__GLIBC__) - -#endif // BASE_OS_COMPAT_NACL_H_
diff --git a/base/rand_util.h b/base/rand_util.h index 91240160..fb2d47182 100644 --- a/base/rand_util.h +++ b/base/rand_util.h
@@ -23,10 +23,7 @@ #include "base/numerics/safe_conversions.h" #include "base/time/time.h" #include "build/build_config.h" - -#if !BUILDFLAG(IS_NACL) #include "third_party/boringssl/src/include/openssl/rand.h" -#endif namespace memory_simulator { class MemoryHolder; @@ -40,9 +37,7 @@ namespace internal { -#if !BUILDFLAG(IS_NACL) void ConfigureBoringSSLBackedRandBytesFieldTrial(); -#endif // Returns a random double in range [0, 1). For use in allocator shim to avoid // infinite recursion. Thread-safe. @@ -193,7 +188,6 @@ ~RandomBitGenerator() = default; }; -#if !BUILDFLAG(IS_NACL) class NonAllocatingRandomBitGenerator { public: using result_type = uint64_t; @@ -209,7 +203,6 @@ NonAllocatingRandomBitGenerator() = default; ~NonAllocatingRandomBitGenerator() = default; }; -#endif // Shuffles [first, last) randomly. Thread-safe. template <typename Itr>
diff --git a/base/rand_util_nacl.cc b/base/rand_util_nacl.cc deleted file mode 100644 index 2ddd184..0000000 --- a/base/rand_util_nacl.cc +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/rand_util.h" - -#include <nacl/nacl_random.h> -#include <stddef.h> -#include <stdint.h> - -#include "base/check_op.h" -#include "base/containers/span.h" - -namespace base { - -void RandBytes(span<uint8_t> output) { - while (!output.empty()) { - size_t nread; - const int error = nacl_secure_random(output.data(), output.size(), &nread); - CHECK_EQ(error, 0); - CHECK_LE(nread, output.size()); - output = output.subspan(nread); - } -} - -} // namespace base
diff --git a/base/rand_util_posix.cc b/base/rand_util_posix.cc index bced7083..94f46d1 100644 --- a/base/rand_util_posix.cc +++ b/base/rand_util_posix.cc
@@ -28,8 +28,9 @@ #include "base/system/sys_info.h" #include "base/time/time.h" #include "build/build_config.h" +#include "third_party/boringssl/src/include/openssl/rand.h" -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #include "third_party/lss/linux_syscall_support.h" #elif BUILDFLAG(IS_MAC) // TODO(crbug.com/40641285): Waiting for this header to appear in the iOS SDK. @@ -37,10 +38,6 @@ #include <sys/random.h> #endif -#if !BUILDFLAG(IS_NACL) -#include "third_party/boringssl/src/include/openssl/rand.h" -#endif - namespace base { namespace { @@ -70,9 +67,7 @@ const int fd_; }; -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ - BUILDFLAG(IS_ANDROID)) && \ - !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) bool KernelSupportsGetRandom() { return base::SysInfo::KernelVersionNumber::Current() >= @@ -94,8 +89,8 @@ } return false; } -#endif // (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || - // BUILDFLAG(IS_ANDROID)) && !BUILDFLAG(IS_NACL) +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || + // BUILDFLAG(IS_ANDROID) } // namespace @@ -103,7 +98,6 @@ namespace { -#if !BUILDFLAG(IS_NACL) // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and // rand_util_win.cc. std::atomic<bool> g_use_boringssl; @@ -122,24 +116,19 @@ bool UseBoringSSLForRandBytes() { return g_use_boringssl.load(std::memory_order_relaxed); } -#endif } // namespace internal namespace { void RandBytesInternal(span<uint8_t> output, bool avoid_allocation) { -#if !BUILDFLAG(IS_NACL) // The BoringSSL experiment takes priority over everything else. if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) { // BoringSSL's RAND_bytes always returns 1. Any error aborts the program. (void)RAND_bytes(output.data(), output.size()); return; } -#endif -#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ - BUILDFLAG(IS_ANDROID)) && \ - !BUILDFLAG(IS_NACL) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) // On Android it is mandatory to check that the kernel _version_ has the // support for a syscall before calling. The same check is made on Linux and // ChromeOS to avoid making a syscall that predictably returns ENOSYS.
diff --git a/base/sync_socket_nacl.cc b/base/sync_socket_nacl.cc deleted file mode 100644 index 6116523..0000000 --- a/base/sync_socket_nacl.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/sync_socket.h" - -#include <errno.h> -#include <limits.h> -#include <stddef.h> -#include <stdio.h> -#include <sys/types.h> -#include <unistd.h> - -#include "base/containers/span.h" -#include "base/notimplemented.h" - -namespace base { - -// static -bool SyncSocket::CreatePair(SyncSocket* socket_a, SyncSocket* socket_b) { - return false; -} - -void SyncSocket::Close() { - handle_.reset(); -} - -size_t SyncSocket::Send(span<const uint8_t> data) { - const ssize_t bytes_written = write(handle(), data.data(), data.size()); - return bytes_written > 0 ? static_cast<size_t>(bytes_written) : 0; -} - -size_t SyncSocket::Receive(span<uint8_t> buffer) { - const ssize_t bytes_read = read(handle(), buffer.data(), buffer.size()); - return bytes_read > 0 ? static_cast<size_t>(bytes_read) : 0; -} - -size_t SyncSocket::ReceiveWithTimeout(span<uint8_t> buffer, TimeDelta timeout) { - NOTIMPLEMENTED(); - return 0; -} - -size_t SyncSocket::Peek() { - NOTIMPLEMENTED(); - return 0; -} - -bool SyncSocket::IsValid() const { - return handle_.is_valid(); -} - -SyncSocket::Handle SyncSocket::handle() const { - return handle_.get(); -} - -SyncSocket::Handle SyncSocket::Release() { - return handle_.release(); -} - -size_t CancelableSyncSocket::Send(span<const uint8_t> data) { - return SyncSocket::Send(data); -} - -bool CancelableSyncSocket::Shutdown() { - Close(); - return true; -} - -// static -bool CancelableSyncSocket::CreatePair(CancelableSyncSocket* socket_a, - CancelableSyncSocket* socket_b) { - return SyncSocket::CreatePair(socket_a, socket_b); -} - -} // namespace base
diff --git a/base/system/sys_info_nacl.cc b/base/system/sys_info_nacl.cc deleted file mode 100644 index 71bfec9..0000000 --- a/base/system/sys_info_nacl.cc +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/system/sys_info.h" - -#include <unistd.h> - -namespace base { - -// static -size_t SysInfo::VMAllocationGranularity() { - return static_cast<size_t>(getpagesize()); -} - -} // namespace base
diff --git a/base/threading/platform_thread_nacl.cc b/base/threading/platform_thread_nacl.cc deleted file mode 100644 index c00861f1..0000000 --- a/base/threading/platform_thread_nacl.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Description: These are stubs for NACL. - -#include "base/threading/platform_thread.h" - -namespace base { -namespace internal { - -bool CanSetThreadTypeToRealtimeAudio() { - return false; -} - -bool SetCurrentThreadTypeForPlatform(ThreadType thread_type, - MessagePumpType pump_type_hint) { - return false; -} - -std::optional<ThreadPriorityForTest> -GetCurrentThreadPriorityForPlatformForTest() { - return std::nullopt; -} -} // namespace internal - -// static -void PlatformThreadBase::SetName(const std::string& name) { - SetNameCommon(name); -} - -} // namespace base
diff --git a/build/fuchsia/cipd/BUILD.gn b/build/fuchsia/cipd/BUILD.gn index 0b0834c..4814f98 100644 --- a/build/fuchsia/cipd/BUILD.gn +++ b/build/fuchsia/cipd/BUILD.gn
@@ -8,6 +8,7 @@ import("//build/cipd/cipd.gni") import("//build/config/chrome_build.gni") +import("//build/config/clang/clang.gni") import("//build/config/compiler/compiler.gni") import("//build/util/process_version.gni") import("//third_party/fuchsia-gn-sdk/src/build_id_dir.gni") @@ -263,13 +264,14 @@ deps = [ "//chrome/test/chromedriver:chromedriver_server($host_toolchain)" ] script = "//build/gn_run_binary.py" sources = [ - "//buildtools/third_party/eu-strip/bin/eu-strip", + "${clang_base_path}/bin/llvm-strip", prog_name, ] outputs = [ _stripped_chromedriver_file ] args = [ - rebase_path("//buildtools/third_party/eu-strip/bin/eu-strip", - root_build_dir), + rebase_path("${clang_base_path}/bin/llvm-strip", root_build_dir), + "--strip-debug", + "--strip-unneeded", "-o", rebase_path(_stripped_chromedriver_file, root_build_dir), rebase_path(prog_name, root_build_dir),
diff --git a/cc/base/features.cc b/cc/base/features.cc index 8b2bd31..2461bdc6 100644 --- a/cc/base/features.cc +++ b/cc/base/features.cc
@@ -273,4 +273,7 @@ "SlimDirectReceiverIpc", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kOverscrollBehaviorRespectedOnAllScrollContainers, + "OverscrollBehaviorRespectedOnAllScrollContainers", + base::FEATURE_DISABLED_BY_DEFAULT); } // namespace features
diff --git a/cc/base/features.h b/cc/base/features.h index 06cf339..b7f0458 100644 --- a/cc/base/features.h +++ b/cc/base/features.h
@@ -244,6 +244,11 @@ // the intermediate IO-thread hop. CC_BASE_EXPORT BASE_DECLARE_FEATURE(kSlimDirectReceiverIpc); +// When enabled, the overscroll behavior will be respected on all scroll +// containers. +CC_BASE_EXPORT BASE_DECLARE_FEATURE( + kOverscrollBehaviorRespectedOnAllScrollContainers); + } // namespace features #endif // CC_BASE_FEATURES_H_
diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc index 59f449e..60ca80a 100644 --- a/cc/input/input_handler.cc +++ b/cc/input/input_handler.cc
@@ -2047,8 +2047,19 @@ break; } + // A scroll container allows chaining if overscroll-behavior is set to + // auto on both axes, or if the Feature Flag is disabled. When the + // scroll container does not allow chaining, we should not skip it, as we + // may need to latch to it. + bool scroll_container_allows_chaining = + !base::FeatureList::IsEnabled( + ::features::kOverscrollBehaviorRespectedOnAllScrollContainers) || + (cur_node->overscroll_behavior.x == OverscrollBehavior::Type::kAuto && + cur_node->overscroll_behavior.y == OverscrollBehavior::Type::kAuto); + if (!cur_node->user_scrollable_horizontal && - !cur_node->user_scrollable_vertical) { + !cur_node->user_scrollable_vertical && + scroll_container_allows_chaining) { continue; }
diff --git a/chrome/OWNERS b/chrome/OWNERS index 48fbe04..0e88b059 100644 --- a/chrome/OWNERS +++ b/chrome/OWNERS
@@ -26,6 +26,7 @@ # Reviewers in PST (GMT-8) dljames@chromium.org +dpenning@chromium.org dtrainor@chromium.org erikchen@chromium.org nyquist@chromium.org
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index d5882c5..880ed6e 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -83,8 +83,8 @@ "java/res/drawable-hdpi/tabswitcher_border_frame_decoration.9.png", "java/res/drawable-hdpi/tabswitcher_border_frame_inner_shadow.9.png", "java/res/drawable-hdpi/tabswitcher_border_frame_shadow.9.png", - "java/res/drawable-ldrtl-v17/btn_back.xml", - "java/res/drawable-ldrtl-v17/btn_forward.xml", + "java/res/drawable-ldrtl/btn_back.xml", + "java/res/drawable-ldrtl/btn_forward.xml", "java/res/drawable-ldrtl/google_pay_with_divider.xml", "java/res/drawable-mdpi/btn_close_white.png", "java/res/drawable-mdpi/btn_left.png", @@ -606,16 +606,10 @@ "java/res/values-large/drawables.xml", "java/res/values-night/colors.xml", "java/res/values-night/drawables.xml", - "java/res/values-sw600dp-v26/styles.xml", - "java/res/values-sw600dp-v27/styles.xml", "java/res/values-sw600dp-v30/styles.xml", "java/res/values-sw600dp/dimens.xml", "java/res/values-sw600dp/styles.xml", "java/res/values-sw600dp/values.xml", - "java/res/values-v25/styles.xml", - "java/res/values-v26/styles.xml", - "java/res/values-v27/styles.xml", - "java/res/values-v28/styles.xml", "java/res/values-v31/styles.xml", "java/res/values-w412dp/bools.xml", "java/res/values-w600dp/dimens.xml",
diff --git a/chrome/android/features/tab_ui/java/res/layout/archived_tabs_auto_delete_promo.xml b/chrome/android/features/tab_ui/java/res/layout/archived_tabs_auto_delete_promo.xml index 7b3d738..53ed9ad 100644 --- a/chrome/android/features/tab_ui/java/res/layout/archived_tabs_auto_delete_promo.xml +++ b/chrome/android/features/tab_ui/java/res/layout/archived_tabs_auto_delete_promo.xml
@@ -74,8 +74,7 @@ android:layout_height="wrap_content" android:textAppearance="@style/TextAppearance.TextSmall.Secondary" android:lineSpacingExtra="4dp" - android:gravity="center_horizontal|top" - android:text="@string/archived_tabs_auto_delete_promo_description"/> + android:gravity="center_horizontal|top"/> </ScrollView> <org.chromium.ui.widget.ButtonCompat
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsMessageService.java index 3a04b90..b053995 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsMessageService.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsMessageService.java
@@ -61,6 +61,7 @@ import org.chromium.components.feature_engagement.Tracker; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.components.tab_group_sync.TabGroupUiActionHandler; +import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -116,6 +117,7 @@ }); } mEndIconView = mCustomCardView.findViewById(R.id.end_image); + mEndIconView.setScaleX(LocalizationUtils.isLayoutRtl() ? -1 : 1); GradientDrawable cardViewBg = (GradientDrawable) mCustomCardView.findViewById(R.id.card).getBackground();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java index c7938f4..8869531c 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoCoordinator.java
@@ -111,6 +111,8 @@ // In case a previous show attempt was interrupted before cleanup completed cleanupSheetResourcesOnly(); + String descriptionString = setPromoDescription(); + mIsFinalizedThisInstance = false; View contentView = @@ -121,7 +123,7 @@ PropertyModelChangeProcessor.create( mModel, contentView, ArchivedTabsAutoDeletePromoViewBinder::bind); - mSheetContent = new ArchivedTabsAutoDeletePromoSheetContent(contentView); + mSheetContent = new ArchivedTabsAutoDeletePromoSheetContent(contentView, descriptionString); mSheetObserver = new EmptyBottomSheetObserver() { @@ -204,6 +206,20 @@ mIsSheetCurrentlyManagedByController = false; } + /* Sets and returns the auto delete delay variable in the description string. */ + private String setPromoDescription() { + int autoDeleteTimeFrame = mTabArchiveSettings.getAutoDeleteTimeDeltaDays(); + String descriptionString = + mContext.getResources() + .getQuantityString( + R.plurals.archived_tabs_auto_delete_promo_description, + autoDeleteTimeFrame, + autoDeleteTimeFrame); + mModel.set( + ArchivedTabsAutoDeletePromoProperties.PROMO_DESCRIPTION_STRING, descriptionString); + return descriptionString; + } + PropertyModel getModelForTesting() { return mModel; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoProperties.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoProperties.java index f4638353..86d66cd5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoProperties.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoProperties.java
@@ -14,6 +14,9 @@ /** Properties for the "Auto Delete Archived Tabs Decision Promo" bottom sheet. */ @NullMarked public class ArchivedTabsAutoDeletePromoProperties { + // Text Properties + public static final WritableObjectPropertyKey<String> PROMO_DESCRIPTION_STRING = + new WritableObjectPropertyKey<>("promo_description_string"); // Click Listener Properties public static final WritableObjectPropertyKey<OnClickListener> ON_YES_BUTTON_CLICK_LISTENER = new WritableObjectPropertyKey<>("on_yes_click"); @@ -21,7 +24,7 @@ new WritableObjectPropertyKey<>("on_no_click"); public static final PropertyKey[] ALL_KEYS = { - ON_YES_BUTTON_CLICK_LISTENER, ON_NO_BUTTON_CLICK_LISTENER + PROMO_DESCRIPTION_STRING, ON_YES_BUTTON_CLICK_LISTENER, ON_NO_BUTTON_CLICK_LISTENER }; /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoSheetContent.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoSheetContent.java index bbbc063..f1aa45a7 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoSheetContent.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoSheetContent.java
@@ -18,14 +18,16 @@ @NullMarked public class ArchivedTabsAutoDeletePromoSheetContent implements BottomSheetContent { private final View mContentView; + private final String mDescriptionString; /** * Constructor. * * @param contentView The inflated view for the bottom sheet. */ - public ArchivedTabsAutoDeletePromoSheetContent(View contentView) { + public ArchivedTabsAutoDeletePromoSheetContent(View contentView, String descriptionString) { mContentView = contentView; + mDescriptionString = descriptionString; } @Override @@ -69,21 +71,21 @@ @Override public String getSheetContentDescription(Context context) { - return context.getString(R.string.archived_tabs_auto_delete_promo_description); + return mDescriptionString; } @Override public @StringRes int getSheetClosedAccessibilityStringId() { - return R.string.archived_tabs_auto_delete_promo_description; + return R.string.archived_tabs_auto_delete_promo_closed; } @Override public @StringRes int getSheetHalfHeightAccessibilityStringId() { - return R.string.archived_tabs_auto_delete_promo_description; + return R.string.archived_tabs_auto_delete_promo_half_height; } @Override public @StringRes int getSheetFullHeightAccessibilityStringId() { - return R.string.archived_tabs_auto_delete_promo_description; + return R.string.archived_tabs_auto_delete_promo_full_height; } }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoViewBinder.java index fe55343..741ecb5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/archived_tabs_auto_delete_promo/ArchivedTabsAutoDeletePromoViewBinder.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.tasks.tab_management.archived_tabs_auto_delete_promo; import android.view.View; +import android.widget.TextView; import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.R; @@ -23,7 +24,12 @@ * @param propertyKey The {@link PropertyKey} that changed. */ public static void bind(PropertyModel model, View view, PropertyKey propertyKey) { - if (ArchivedTabsAutoDeletePromoProperties.ON_YES_BUTTON_CLICK_LISTENER == propertyKey) { + if (ArchivedTabsAutoDeletePromoProperties.PROMO_DESCRIPTION_STRING == propertyKey) { + TextView description = view.findViewById(R.id.promo_description_text); + description.setText( + model.get(ArchivedTabsAutoDeletePromoProperties.PROMO_DESCRIPTION_STRING)); + } else if (ArchivedTabsAutoDeletePromoProperties.ON_YES_BUTTON_CLICK_LISTENER + == propertyKey) { ButtonCompat yesButton = view.findViewById(R.id.promo_yes_button); yesButton.setOnClickListener( model.get(ArchivedTabsAutoDeletePromoProperties.ON_YES_BUTTON_CLICK_LISTENER));
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd index 050ed05..ed8e90dc2 100644 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
@@ -978,8 +978,20 @@ <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_TITLE" desc="Title text for the Auto Delete Decision Bottom Sheet."> Keep your inactive section tidy? </message> - <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION" desc="Description text or the Auto Delete Decision Bottom Sheet."> - Chrome automatically closes items in the inactive section that you haven't used in 3 months. You can turn this off now or anytime in Settings. + <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION" desc="Description text for the Auto Delete Decision Bottom Sheet."> + {AUTO_DELETE_DELAY, plural, + =1 {Chrome automatically closes items in the inactive section that you haven't used in <ph name="AUTO_DELETE_DELAY_ONE">%1$d<ex>1</ex></ph> day. You can turn this off now or anytime in Settings.} + other {Chrome automatically closes items in the inactive section that you haven't used in <ph name="AUTO_DELETE_DELAY_MANY">%1$d<ex>14</ex></ph> days. You can turn this off now or anytime in Settings.} + } + </message> + <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_CLOSED" desc="The announcement when the Tabs Auto Delete Promo bottom sheet is closed."> + Notice about Tabs Auto Delete changes closed. + </message> + <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_HALF_HEIGHT" desc="The announcement when the Tabs Auto Delete Promo bottom sheet is opened to half height."> + Notice about Tabs Auto Delete at half height. + </message> + <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_FULL_HEIGHT" desc="The announcement when the Tabs Auto Delete Promo bottom sheet is opened to full height."> + Notice about Tabs Auto Delete at full height </message> <message name="IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_YES_BUTTON" desc="Button to accept the Auto Delete feature. "> Yes. I'm in
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_CLOSED.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_CLOSED.png.sha1 new file mode 100644 index 0000000..dd8046e --- /dev/null +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_CLOSED.png.sha1
@@ -0,0 +1 @@ +a33d89f013a265362427f13ed144772431a36487 \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION.png.sha1 index e7070f5..dd8046e 100644 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION.png.sha1 +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_DESCRIPTION.png.sha1
@@ -1 +1 @@ -e75b484ed67789852c2066050afb58dc5dcb13c6 \ No newline at end of file +a33d89f013a265362427f13ed144772431a36487 \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_FULL_HEIGHT.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_FULL_HEIGHT.png.sha1 new file mode 100644 index 0000000..dd8046e --- /dev/null +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_FULL_HEIGHT.png.sha1
@@ -0,0 +1 @@ +a33d89f013a265362427f13ed144772431a36487 \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_HALF_HEIGHT.png.sha1 b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_HALF_HEIGHT.png.sha1 new file mode 100644 index 0000000..dd8046e --- /dev/null +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ARCHIVED_TABS_AUTO_DELETE_PROMO_HALF_HEIGHT.png.sha1
@@ -0,0 +1 @@ +a33d89f013a265362427f13ed144772431a36487 \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java index 1d08133..90ae7906 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabListEditorTest.java
@@ -385,7 +385,8 @@ Rect widestUnoccludedRect = new Rect(windowRect.left, 0, windowRect.right, appHeaderHeight); var state = new AppHeaderState(windowRect, widestUnoccludedRect, true); - mAppHeaderStateProvider.setStateForTesting(true, state); + mAppHeaderStateProvider.setStateForTesting( + /* isInDesktopWindow= */ true, state, /* isFocused= */ true); }); prepareBlankTab(2, false); @@ -398,7 +399,8 @@ () -> { // Exit desktop window. var state = new AppHeaderState(windowRect, new Rect(), false); - mAppHeaderStateProvider.setStateForTesting(false, state); + mAppHeaderStateProvider.setStateForTesting( + /* isInDesktopWindow= */ false, state, /* isFocused= */ true); }); // Verify margin is reset.
diff --git a/chrome/android/java/res/drawable-ldrtl-v17/btn_back.xml b/chrome/android/java/res/drawable-ldrtl/btn_back.xml similarity index 100% rename from chrome/android/java/res/drawable-ldrtl-v17/btn_back.xml rename to chrome/android/java/res/drawable-ldrtl/btn_back.xml
diff --git a/chrome/android/java/res/drawable-ldrtl-v17/btn_forward.xml b/chrome/android/java/res/drawable-ldrtl/btn_forward.xml similarity index 100% rename from chrome/android/java/res/drawable-ldrtl-v17/btn_forward.xml rename to chrome/android/java/res/drawable-ldrtl/btn_forward.xml
diff --git a/chrome/android/java/res/values-sw600dp-v26/styles.xml b/chrome/android/java/res/values-sw600dp-v26/styles.xml deleted file mode 100644 index d17edf5..0000000 --- a/chrome/android/java/res/values-sw600dp-v26/styles.xml +++ /dev/null
@@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2018 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode"> - <item name="android:statusBarColor">@android:color/black</item> - <item name="android:windowLightStatusBar">false</item> - </style> - - <style name="Theme.Chromium.Settings" parent="Base.Theme.Chromium.Settings"> - <item name="android:statusBarColor">@android:color/black</item> - <item name="android:windowLightStatusBar">false</item> - </style> -</resources> -
diff --git a/chrome/android/java/res/values-sw600dp-v27/styles.xml b/chrome/android/java/res/values-sw600dp-v27/styles.xml deleted file mode 100644 index 91ed9276..0000000 --- a/chrome/android/java/res/values-sw600dp-v27/styles.xml +++ /dev/null
@@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2017 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <style name="Theme.Chromium.WithWindowAnimation" - parent="Base.Theme.Chromium.WithWindowAnimation"/> - <style name="Theme.Chromium.DialogWhenLarge" parent="Base.Theme.Chromium.DialogWhenLarge"/> - <style name="Theme.Chromium.Activity.Fullscreen" - parent="Base.Theme.Chromium.Activity.Fullscreen" /> -</resources>
diff --git a/chrome/android/java/res/values-sw600dp/styles.xml b/chrome/android/java/res/values-sw600dp/styles.xml index c20f038..651dbfa 100644 --- a/chrome/android/java/res/values-sw600dp/styles.xml +++ b/chrome/android/java/res/values-sw600dp/styles.xml
@@ -8,5 +8,17 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode"> <item name="android:statusBarColor">@android:color/black</item> + <item name="android:windowLightStatusBar">false</item> </style> + + <style name="Theme.Chromium.Settings" parent="Base.Theme.Chromium.Settings"> + <item name="android:statusBarColor">@android:color/black</item> + <item name="android:windowLightStatusBar">false</item> + </style> + + <style name="Theme.Chromium.WithWindowAnimation" + parent="Base.Theme.Chromium.WithWindowAnimation"/> + <style name="Theme.Chromium.DialogWhenLarge" parent="Base.Theme.Chromium.DialogWhenLarge"/> + <style name="Theme.Chromium.Activity.Fullscreen" + parent="Base.Theme.Chromium.Activity.Fullscreen" /> </resources>
diff --git a/chrome/android/java/res/values-v25/styles.xml b/chrome/android/java/res/values-v25/styles.xml deleted file mode 100644 index 6b5f73f..0000000 --- a/chrome/android/java/res/values-v25/styles.xml +++ /dev/null
@@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2016 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources xmlns:tools="http://schemas.android.com/tools"> - <style name="LauncherTheme" parent="Theme.BrowserUI.NoDisplay" /> -</resources>
diff --git a/chrome/android/java/res/values-v26/styles.xml b/chrome/android/java/res/values-v26/styles.xml deleted file mode 100644 index 8a34caf..0000000 --- a/chrome/android/java/res/values-v26/styles.xml +++ /dev/null
@@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2018 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode"> - <item name="android:statusBarColor">@macro/default_bg_color</item> - <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> - </style> -</resources> -
diff --git a/chrome/android/java/res/values-v27/styles.xml b/chrome/android/java/res/values-v27/styles.xml deleted file mode 100644 index bbe8f0e..0000000 --- a/chrome/android/java/res/values-v27/styles.xml +++ /dev/null
@@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2017 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <style name="Theme.Chromium.WithWindowAnimation" parent="Base.Theme.Chromium.WithWindowAnimation"> - <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> - <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> - <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> - </style> - <style name="Base.V27.Theme.Chromium.Settings" parent="Base.Theme.Chromium.Settings"> - <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> - <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> - <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> - </style> - <style name="Base.V27.Theme.Chromium.DialogWhenLarge" parent="Base.Theme.Chromium.DialogWhenLarge"> - <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> - <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> - <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> - </style> - <style name="Base.V27.Theme.Chromium.Activity.Fullscreen" - parent="Base.Theme.Chromium.Activity.Fullscreen"> - <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> - <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> - <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> - </style> - <style name="Theme.Chromium.SigninAndHistorySyncActivity" - parent="Base.Theme.Chromium.SigninAndHistorySyncActivity"> - <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> - </style> -</resources>
diff --git a/chrome/android/java/res/values-v28/styles.xml b/chrome/android/java/res/values-v28/styles.xml deleted file mode 100644 index 6a03e03..0000000 --- a/chrome/android/java/res/values-v28/styles.xml +++ /dev/null
@@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2019 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> - -<resources> - <!-- The windowLightStatusBar attribute was added in API 23, but we avoid using it via XML prior - to 28 due to: https://crbug.com/884144 and https://crbug.com/1014844 --> - <style name="Theme.Chromium.Settings" parent="Base.V27.Theme.Chromium.Settings"> - <item name="android:statusBarColor">@macro/default_bg_color</item> - <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> - </style> - <style name="Theme.Chromium.Activity.Fullscreen" parent="Base.V27.Theme.Chromium.Activity.Fullscreen"> - <item name="android:statusBarColor">@macro/default_bg_color</item> - <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> - </style> - <style name="Theme.Chromium.DialogWhenLarge" parent="Base.V27.Theme.Chromium.DialogWhenLarge"> - <item name="android:statusBarColor">@macro/default_bg_color</item> - <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> - </style> -</resources>
diff --git a/chrome/android/java/res/values/styles.xml b/chrome/android/java/res/values/styles.xml index 6d89f36..a572c5eb 100644 --- a/chrome/android/java/res/values/styles.xml +++ b/chrome/android/java/res/values/styles.xml
@@ -8,23 +8,16 @@ <resources xmlns:tools="http://schemas.android.com/tools"> <!-- TODO(huayinz): Move themes to another xml file. --> <!-- Application themes --> - <!-- On Android N, if the ChromeLauncherActivity is NoDisplay then - intents are not always immediately sent when Chrome is docked to - the top of the screen in multi-window mode. Use Translucent.NoTitleBar - for the theme instead. See crbug.com/645074. --> - <style name="LauncherTheme" parent="Theme.BrowserUI.Translucent.NoTitleBar" /> + <style name="LauncherTheme" parent="Theme.BrowserUI.NoDisplay" /> - <style name="Base.V21.Theme.Chromium" parent="Theme.BrowserUI.DayNight"> + <style name="Base.Theme.Chromium" parent="Theme.BrowserUI.DayNight"> <!-- Set android alert dialog attributes because the context menu dialog is OS-dependent. --> <item name="android:alertDialogTheme">@style/ThemeOverlay.BrowserUI.AlertDialog</item> </style> - <style name="Base.Theme.Chromium" parent="Base.V21.Theme.Chromium" /> <style name="Base.Theme.Chromium.WithWindowAnimation"> <item name="android:windowContentOverlay">@null</item> - - <!-- Navigation Transitions, requires API level 21 --> <item name="android:windowAllowEnterTransitionOverlap">false</item> <item name="android:windowAllowReturnTransitionOverlap">true</item> <item name="android:windowContentTransitions">true</item> @@ -35,18 +28,25 @@ </style> <style name="Theme.Chromium" parent="Base.Theme.Chromium" /> - <style name="Theme.Chromium.WithWindowAnimation" - parent="Base.Theme.Chromium.WithWindowAnimation" /> + <style name="Theme.Chromium.WithWindowAnimation" parent="Base.Theme.Chromium.WithWindowAnimation"> + <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> + <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> + <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> + </style> <!-- Activity themes --> <style name="Theme.Chromium.Activity" parent="Theme.Chromium.WithWindowAnimation" /> <!-- This is distinct from Theme.Chromium.Activity.Fullscreen.Transparent, which makes the payment handler window overlap the bottom nav bar. --> - <style name="Base.Theme.Chromium.Activity.Fullscreen" parent="Theme.BrowserUI.DayNight" /> - <style name="Base.V27.Theme.Chromium.Activity.Fullscreen" - parent="Base.Theme.Chromium.Activity.Fullscreen" /> - <style name="Theme.Chromium.Activity.Fullscreen" - parent="Base.V27.Theme.Chromium.Activity.Fullscreen" /> + <style name="Base.Theme.Chromium.Activity.Fullscreen" parent="Theme.BrowserUI.DayNight"> + <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> + <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> + <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> + <item name="android:statusBarColor">@macro/default_bg_color</item> + <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> + </style> + <style name="Theme.Chromium.Activity.Fullscreen" parent="Base.Theme.Chromium.Activity.Fullscreen" /> + <style name="Theme.Chromium.Activity.Fullscreen.Transparent"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> @@ -80,6 +80,11 @@ <item name="preferenceTheme">@style/PreferenceTheme</item> <item name="alertDialogTheme">@style/ThemeOverlay.BrowserUI.AlertDialog</item> <item name="searchViewStyle">@style/Widget.AppCompat.SearchView.ActionBar</item> + <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> + <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> + <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> + <item name="android:statusBarColor">@macro/default_bg_color</item> + <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> <!-- Text style attributes used by the preference_material.xml layout. --> <item name="android:textAppearanceListItem">@style/TextAppearance.TextLarge.Primary</item> @@ -87,8 +92,7 @@ <item name="android:textAppearanceListItemSecondary">@style/TextAppearance.TextMedium.Secondary</item> <item name="android:textColorSecondary">@color/default_text_color_secondary_list</item> </style> - <style name="Base.V27.Theme.Chromium.Settings" parent="Base.Theme.Chromium.Settings" /> - <style name="Theme.Chromium.Settings" parent="Base.V27.Theme.Chromium.Settings" /> + <style name="Theme.Chromium.Settings" parent="Base.Theme.Chromium.Settings" /> <style name="Theme.Chromium.Settings.ManageSpace"> <!-- With ActionBar --> @@ -117,7 +121,9 @@ <item name="android:windowAnimationStyle">@style/SigninAndHistorySyncActivityAnimation</item> </style> <style name="Theme.Chromium.SigninAndHistorySyncActivity" - parent="Base.Theme.Chromium.SigninAndHistorySyncActivity" /> + parent="Base.Theme.Chromium.SigninAndHistorySyncActivity"> + <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> + </style> <!-- TODO(crbug.com/345176436): This animation style is used to set the enter animation for the history sync dialog. This animation should be @@ -149,13 +155,17 @@ <item name="colorControlHighlight">@color/control_highlight_color</item> <item name="spinnerStyle">@style/SpinnerStyle</item> <item name="textInputStyle">@style/Widget.BrowserUI.TextInputLayout</item> + <item name="android:navigationBarColor">@macro/bottom_system_nav_color</item> + <item name="android:navigationBarDividerColor">@macro/bottom_system_nav_divider_color</item> + <item name="android:windowLightNavigationBar">@bool/window_light_navigation_bar</item> + <item name="android:statusBarColor">@macro/default_bg_color</item> + <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> <!-- Remove ActionBar --> <item name="windowNoTitle">true</item> <item name="windowActionBar">false</item> </style> - <style name="Base.V27.Theme.Chromium.DialogWhenLarge" parent="Base.Theme.Chromium.DialogWhenLarge" /> - <style name="Theme.Chromium.DialogWhenLarge" parent="Base.V27.Theme.Chromium.DialogWhenLarge" /> + <style name="Theme.Chromium.DialogWhenLarge" parent="Base.Theme.Chromium.DialogWhenLarge" /> <style name="DimmingDialog" parent="Base.Theme.Chromium.DialogWhenLarge"> <item name="android:windowLightNavigationBar" tools:targetApi="28">false</item> </style>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java index 131d5d2..5181e36 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditor.java
@@ -93,7 +93,6 @@ protected @MonotonicNonNull EditText mExpirationDate; protected @MonotonicNonNull EditText mCvc; protected @MonotonicNonNull ImageView mCvcHintImage; - private boolean mIsValidExpirationDate; private int mInitialExpirationYearPos; protected Button mScanButton; private CreditCardScannerManager mScannerManager; @@ -148,6 +147,9 @@ @Override public void afterTextChanged(Editable s) { mScannerManager.fieldEdited(FieldType.NUMBER); + if (mNumberLabel.getError() != null) { + validateCardNumberAndUpdateError(removeSpaces(s.toString())); + } } }); @@ -236,22 +238,15 @@ @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - boolean isAddressSpinnerUpdated = - parent == mBillingAddress && position != mInitialBillingAddressPos; - if (isAddressSpinnerUpdated) { - updateSaveButtonEnabled(); - } if (!mIsCvcStorageEnabled) { // If the month spinner was updated. if (parent == mExpirationMonth && position != mInitialExpirationMonthPos) { mScannerManager.fieldEdited(FieldType.MONTH); - updateSaveButtonEnabled(); } // If the year spinner was updated. if (parent == mExpirationYear && position != mInitialExpirationYearPos) { mScannerManager.fieldEdited(FieldType.YEAR); - updateSaveButtonEnabled(); } } mScannerManager.fieldEdited(FieldType.UNKNOWN); @@ -259,7 +254,6 @@ @Override public void afterTextChanged(Editable s) { - updateSaveButtonEnabled(); mScannerManager.fieldEdited(FieldType.UNKNOWN); } @@ -371,20 +365,15 @@ @Override protected boolean saveEntry() { - // Remove all spaces in editText. - String cardNumber = mNumberText.getText().toString().replaceAll("\\s+", ""); - // Issuer network will be empty if credit card number is not valid. - if (TextUtils.isEmpty( - PersonalDataManager.getBasicCardIssuerNetwork( - cardNumber, /* emptyIfInvalid= */ true))) { - mNumberLabel.setError( - mContext.getString(R.string.payments_card_number_invalid_validation_message)); + if (!validateFormAndUpdateErrorAndFocusErrorField()) { return false; } PersonalDataManager personalDataManager = PersonalDataManagerFactory.getForProfile(getProfile()); - CreditCard card = personalDataManager.getCreditCardForNumber(cardNumber); + CreditCard card = + personalDataManager.getCreditCardForNumber( + removeSpaces(mNumberText.getText().toString())); card.setGUID(mGUID); card.setOrigin(SETTINGS_ORIGIN); card.setName(mNameText.getText().toString().trim()); @@ -393,12 +382,6 @@ assumeNonNull(mExpirationDate); assumeNonNull(mCvc); String expirationDate = mExpirationDate.getText().toString().trim(); - if (TextUtils.isEmpty(expirationDate)) { - mExpirationDate.setError( - mContext.getString( - R.string.autofill_credit_card_editor_invalid_expiration_date)); - return false; - } card.setMonth(AutofillLocalCardEditor.getExpirationMonth(expirationDate)); card.setYear(AutofillLocalCardEditor.getExpirationYear(expirationDate)); card.setCvc(mCvc.getText().toString().trim()); @@ -465,6 +448,48 @@ return true; } + @VisibleForTesting + public boolean validateFormAndUpdateErrorAndFocusErrorField() { + if (!validateCardNumberAndUpdateError(removeSpaces(mNumberText.getText().toString()))) { + mNumberText.requestFocus(); + return false; + } + + if (mIsCvcStorageEnabled) { + assumeNonNull(mExpirationDate); + if (!validateExpirationDateAndUpdateError( + mExpirationDate.getText().toString().trim())) { + mExpirationDate.requestFocus(); + return false; + } + } + + if (!mIsValidNickname) { + mNicknameText.requestFocus(); + return false; + } + + return true; + } + + private boolean validateCardNumberAndUpdateError(String cardNumber) { + // Issuer network will be empty if credit card number is not valid. + if (TextUtils.isEmpty( + PersonalDataManager.getBasicCardIssuerNetwork( + cardNumber, /* emptyIfInvalid= */ true))) { + mNumberLabel.setError( + mContext.getString(R.string.payments_card_number_invalid_validation_message)); + return false; + } else { + mNumberLabel.setError(null); + return true; + } + } + + private String removeSpaces(String s) { + return s.replaceAll("\\s+", ""); + } + @Override protected void deleteEntry() { if (mGUID != null) { @@ -475,6 +500,7 @@ @Override protected void initializeButtons(View v) { super.initializeButtons(v); + mDoneButton.setEnabled(true); // Listen for change to inputs. Enable the save button after something has changed. mNameText.addTextChangedListener(this); @@ -532,17 +558,6 @@ addCardDataToEditFields(); } - private void updateSaveButtonEnabled() { - // Enable save button if credit card number is not empty and the nickname is valid - // and the expiration date is valid. We validate the credit card number when the user - // presses the save button. - boolean enabled = - !TextUtils.isEmpty(mNumberText.getText()) - && mIsValidNickname - && (!mIsCvcStorageEnabled || mIsValidExpirationDate); - mDoneButton.setEnabled(enabled); - } - private TextWatcher nicknameTextWatcher() { return new EmptyTextWatcher() { @Override @@ -554,7 +569,6 @@ ? "" : mContext.getString( R.string.autofill_credit_card_editor_invalid_nickname)); - updateSaveButtonEnabled(); } }; } @@ -572,25 +586,8 @@ s.insert(SEPARATOR_INDEX, EXPIRATION_DATE_SEPARATOR); } if (s.length() == VALID_DATE_LENGTH) { - if (!validExpirationDate(s.toString())) { - mExpirationDate.setError( - mContext.getString( - R.string - .autofill_credit_card_editor_invalid_expiration_date)); - } else if (!validFutureExpirationDate(s.toString())) { - mExpirationDate.setError( - mContext.getString( - R.string.autofill_credit_card_editor_expired_card)); - } else if (mExpirationDate.getError() != null) { - // Removes error message if a previous error exists and the user inputs - // a valid date. - mExpirationDate.setError(null); - } + validateExpirationDateAndUpdateError(s.toString()); } - mIsValidExpirationDate = - validExpirationDate(s.toString()) - && validFutureExpirationDate(s.toString()); - updateSaveButtonEnabled(); mScannerManager.fieldEdited(FieldType.MONTH); mScannerManager.fieldEdited(FieldType.YEAR); @@ -598,6 +595,25 @@ }; } + private boolean validateExpirationDateAndUpdateError(String expirationDate) { + assumeNonNull(mExpirationDate); + if (!validExpirationDate(expirationDate)) { + mExpirationDate.setError( + mContext.getString( + R.string.autofill_credit_card_editor_invalid_expiration_date)); + return false; + } else if (!validFutureExpirationDate(expirationDate)) { + mExpirationDate.setError( + mContext.getString(R.string.autofill_credit_card_editor_expired_card)); + return false; + } else if (mExpirationDate.getError() != null) { + // Removes error message if a previous error exists and the user inputs + // a valid date. + mExpirationDate.setError(null); + } + return true; + } + private TextWatcher creditCardNumberTextWatcherForCvc() { assumeNonNull(mCvcHintImage); return new EmptyTextWatcher() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java index 706bca7..d2ea147b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java
@@ -13,10 +13,8 @@ import android.content.ContentProvider; import android.content.Context; import android.content.Intent; -import android.os.Build; import androidx.annotation.IntDef; -import androidx.annotation.RequiresApi; import org.chromium.base.BundleUtils; import org.chromium.base.ContextUtils; @@ -37,7 +35,6 @@ * <p>Note: this workaround is not needed for services, since they always uses the base module's * ClassLoader, see b/169196314 for more details. */ -@RequiresApi(Build.VERSION_CODES.P) @NullMarked public class SplitCompatAppComponentFactory extends AppComponentFactory { private static final String TAG = "SplitCompat";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehavior.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehavior.java index 309af37..8d54fb6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehavior.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehavior.java
@@ -4,11 +4,12 @@ package org.chromium.chrome.browser.customtabs; -import static androidx.browser.customtabs.CustomTabsIntent.OPEN_IN_BROWSER_STATE_DEFAULT; +import static androidx.browser.customtabs.CustomTabsIntent.OPEN_IN_BROWSER_STATE_OFF; import static androidx.browser.customtabs.CustomTabsIntent.SHARE_STATE_OFF; import static org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant.OPEN_IN_BROWSER; import static org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant.SHARE; +import static org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant.UNKNOWN; import android.content.Context; import android.graphics.drawable.Drawable; @@ -169,14 +170,14 @@ @Override public @AdaptiveToolbarButtonVariant int getSegmentationDefault() { - return ChromeFeatureList.sCctAdaptiveButtonDefaultVariant.getValue(); + var defVariant = ChromeFeatureList.sCctAdaptiveButtonDefaultVariant.getValue(); + return isButtonDuplicated(defVariant) ? UNKNOWN : defVariant; } @ExperimentalOpenInBrowser private boolean isOpenInBrowserButtonEnabled() { return ChromeFeatureList.sCctAdaptiveButtonEnableOpenInBrowser.getValue() - && mIntentDataProvider.getOpenInBrowserButtonState() - == OPEN_IN_BROWSER_STATE_DEFAULT; + && mIntentDataProvider.getOpenInBrowserButtonState() != OPEN_IN_BROWSER_STATE_OFF; } private boolean isShareButtonEnabled() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java index 4d0c2907..78f398615 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -89,6 +89,7 @@ import org.chromium.chrome.browser.flags.ActivityType; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.share.ShareUtils; +import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant; import org.chromium.chrome.browser.ui.google_bottom_bar.GoogleBottomBarCoordinator; import org.chromium.chrome.browser.ui.google_bottom_bar.proto.IntentParams.GoogleBottomBarIntentParams; import org.chromium.chrome.browser.ui.web_app_header.WebAppHeaderUtils; @@ -937,7 +938,7 @@ mShowShareItemInMenu = true; } } else if (mShareState == CustomTabsIntent.SHARE_STATE_ON) { - if (mToolbarButtons.isEmpty()) { + if (mToolbarButtons.isEmpty() || isCpaOnlyOpenInBrowserDefault()) { mToolbarButtons.add( CustomButtonParamsImpl.createShareButton( context, getColorProvider().getToolbarColor())); @@ -981,7 +982,7 @@ } if (openInBrowserState == CustomTabsButtonState.BUTTON_STATE_ON) { - if (mToolbarButtons.isEmpty()) { + if (mToolbarButtons.isEmpty() || isCpaOnlyOpenInBrowserDefault()) { mToolbarButtons.add( CustomButtonParamsImpl.createOpenInBrowserButton( context, getColorProvider().getToolbarColor())); @@ -1762,4 +1763,11 @@ IntentUtils.safeGetIntExtra(getIntent(), EXTRA_ANDROID_BROWSER_HELPER_VERSION, 0); return value != 0 ? Integer.valueOf(value) : null; } + + private boolean isCpaOnlyOpenInBrowserDefault() { + return ChromeFeatureList.sCctAdaptiveButtonContextualOnly.getValue() + && ChromeFeatureList.sCctAdaptiveButtonEnableOpenInBrowser.getValue() + && ChromeFeatureList.sCctAdaptiveButtonDefaultVariant.getValue() + == AdaptiveToolbarButtonVariant.OPEN_IN_BROWSER; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java index 710579cf3..972a65c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -1499,14 +1499,6 @@ View background = optionalButton.findViewById(R.id.swappable_icon_secondary_background); background.setPaddingRelative(paddingStart, paddingVert, paddingEnd, paddingVert); - // Update dev button spacing if present. - View firstButton = mCustomActionButtons.getChildAt(0); - if (firstButton != optionalButton) { - // Give 24dp/0dp padding to the first button to have even 16dp spacing. - paddingStart = getDimensionPx(R.dimen.custom_tabs_toolbar_button_spacer_24); - firstButton.setPaddingRelative( - paddingStart, /* top= */ 0, /* end= */ 0, /* bottom= */ 0); - } mOptionalButtonCoordinator = new OptionalButtonCoordinator( optionalButton, @@ -1541,6 +1533,16 @@ optionalButtonContainer, true, mOptionalButtonCoordinator::setCanChangeVisibility); + + // Update the spacing between dev button and the menu icon if present. + View firstButton = mCustomActionButtons.getChildAt(0); + if (firstButton != optionalButton + && !mButtonVisibilityRule.isSuppressed(ButtonId.MTB)) { + // Give 24dp/0dp padding to the first button to have even 16dp spacing. + paddingStart = getDimensionPx(R.dimen.custom_tabs_toolbar_button_spacer_24); + firstButton.setPaddingRelative( + paddingStart, /* top= */ 0, /* end= */ 0, /* bottom= */ 0); + } return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java index 5194db7..3dff231 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureActivity.java
@@ -28,7 +28,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; import org.jni_zero.CalledByNative; @@ -671,7 +670,6 @@ } @Override - @RequiresApi(api = Build.VERSION_CODES.O) public void onPictureInPictureModeChanged( boolean isInPictureInPictureMode, Configuration newConfig) { super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationSuspender.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationSuspender.java index a412ffa8..10eb969 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationSuspender.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationSuspender.java
@@ -10,11 +10,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Icon; import android.net.Uri; -import android.os.Build; import android.text.TextUtils; -import androidx.annotation.RequiresApi; - import org.jni_zero.JniType; import org.jni_zero.NativeMethods; @@ -213,7 +210,6 @@ }); } - @RequiresApi(Build.VERSION_CODES.P) private Bitmap getBitmapFromIcon(Icon icon) { if (icon == null || icon.getType() != Icon.TYPE_BITMAP) return null; return ((BitmapDrawable) icon.loadDrawable(mContext)).getBitmap();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java index 0978f31c..7d9d7212 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java
@@ -968,6 +968,7 @@ boolean isLensButtonVisible, boolean isComposeplateButtonVisible) { if (!mManager.isCurrentPage() + || (mSearchBoxCoordinator.getView().getVisibility() != View.VISIBLE) || (mPreviousVoiceSearchButtonVisible != null && isVoiceSearchButtonVisible == mPreviousVoiceSearchButtonVisible && mPreviousLensButtonVisible != null
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java index aa714c1..2ecc585 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ChromePaymentRequestService.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.payments; import static org.chromium.build.NullUtil.assertNonNull; +import static org.chromium.build.NullUtil.assumeNonNull; import android.app.Activity; import android.content.Context; @@ -44,8 +45,10 @@ import org.chromium.components.payments.PaymentRequestServiceUtil; import org.chromium.components.payments.PaymentRequestSpec; import org.chromium.components.payments.PaymentRequestUpdateEventListener; +import org.chromium.components.payments.PaymentRequestWebContentsData; import org.chromium.components.payments.PaymentResponseHelper; import org.chromium.components.payments.PaymentResponseHelperInterface; +import org.chromium.components.payments.SPCTransactionMode; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationAuthnController; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationAuthnController.SpcResponseStatus; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationController; @@ -374,6 +377,12 @@ PaymentMethodData spcMethodData = assertNonNull(mSpec.getMethodData().get(MethodStrings.SECURE_PAYMENT_CONFIRMATION)); + PaymentRequestWebContentsData paymentRequestWebContentsData = + PaymentRequestWebContentsData.from(mWebContents); + assumeNonNull(paymentRequestWebContentsData); + @SPCTransactionMode + int transactionMode = paymentRequestWebContentsData.getSPCTransactionMode(); + if (ContentFeatureMap.isEnabled(BlinkFeatures.SECURE_PAYMENT_CONFIRMATION_UX_REFRESH)) { assert mSpcController == null; WindowAndroid windowAndroid = @@ -427,7 +436,8 @@ spcMethodData.securePaymentConfirmation.rpId, spcMethodData.securePaymentConfirmation.showOptOut, /* informOnly= */ true, - responseCallback); + responseCallback, + transactionMode); return mSpcController.show(); } @@ -522,6 +532,12 @@ assertNonNull( mSpec.getMethodData().get(MethodStrings.SECURE_PAYMENT_CONFIRMATION)); + PaymentRequestWebContentsData paymentRequestWebContentsData = + PaymentRequestWebContentsData.from(mWebContents); + assumeNonNull(paymentRequestWebContentsData); + @SPCTransactionMode + int transactionMode = paymentRequestWebContentsData.getSPCTransactionMode(); + if (ContentFeatureMap.isEnabled(BlinkFeatures.SECURE_PAYMENT_CONFIRMATION_UX_REFRESH)) { assert mSpcController == null; Callback<Integer> responseCallback = @@ -580,7 +596,8 @@ spcMethodData.securePaymentConfirmation.rpId, spcMethodData.securePaymentConfirmation.showOptOut, /* informOnly= */ false, - responseCallback); + responseCallback, + transactionMode); if (mSpcController.show()) { mJourneyLogger.setShown();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/AutofillSessionLifetimeController.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/AutofillSessionLifetimeController.java index 3de07af..f69de016 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/AutofillSessionLifetimeController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/AutofillSessionLifetimeController.java
@@ -5,11 +5,8 @@ package org.chromium.chrome.browser.tab; import android.app.Activity; -import android.os.Build; import android.view.autofill.AutofillManager; -import androidx.annotation.RequiresApi; - import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.ActivityTabProvider; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -49,7 +46,6 @@ private final Activity mActivity; private final ActivityTabProvider.ActivityTabTabObserver mActivityTabObserver; - @RequiresApi(Build.VERSION_CODES.O) public AutofillSessionLifetimeController( Activity activity, ActivityLifecycleDispatcher lifecycleDispatcher,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java index f3e4fd5c..7ea1450 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java
@@ -7,10 +7,8 @@ import android.content.Intent; import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutManager; -import android.os.Build; import android.os.Build.VERSION_CODES; -import androidx.annotation.RequiresApi; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -56,8 +54,6 @@ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@RequiresApi(VERSION_CODES.N_MR1) -@MinAndroidSdkLevel(Build.VERSION_CODES.N_MR1) @DoNotBatch(reason = "This class tests activity start behavior and thus cannot be batched.") public class LauncherShortcutTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/VirtualKeyboardResizeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/VirtualKeyboardResizeTest.java index c03b619..19135ff 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/VirtualKeyboardResizeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/VirtualKeyboardResizeTest.java
@@ -7,7 +7,6 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; -import android.os.Build; import android.util.JsonReader; import androidx.test.filters.MediumTest; @@ -29,7 +28,6 @@ import org.chromium.base.test.util.CriteriaNotSatisfiedException; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.preferences.Pref; @@ -347,7 +345,6 @@ */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.Q) // Run on Android 10 (API 29) and newer @DisabledTest(message = "crbug.com/421296274") public void testResizesVisualMetaTag() throws Throwable { startMainActivityWithURL("/chrome/test/data/android/about.html");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java index a94f5397..cb30afa8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tab_activity_glue/TabletPhoneLayoutChangeTest.java
@@ -7,7 +7,6 @@ import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; import android.content.res.Configuration; -import android.os.Build; import androidx.test.filters.MediumTest; @@ -25,7 +24,6 @@ import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -98,7 +96,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.Q) // See crbug.com/404979701. public void testUrlBarStateRetention() throws TimeoutException { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); ToolbarManager toolbarManager = cta.getToolbarManager(); @@ -135,7 +132,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.Q) // See crbug.com/404979701. public void testTabSwitcherStateRetention() throws TimeoutException { ChromeTabbedActivity cta = mActivityTestRule.getActivity();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillUpstreamTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillUpstreamTest.java index 987eaf4c..bb0d80c86 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillUpstreamTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillUpstreamTest.java
@@ -8,8 +8,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; -import android.os.Build; - import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.MediumTest; @@ -21,7 +19,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.infobar.AutofillSaveCardInfoBar; @@ -104,9 +101,6 @@ @Test @MediumTest @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) - @DisableIf.Build( - sdk_is_less_than = Build.VERSION_CODES.Q, - message = "https://crbug.com/1424178") public void testSaveCardInfoBarWithAllFieldsFilled() throws TimeoutException { mActivityTestRule.loadUrl(mServer.getURL(TEST_FORM_URL)); final WebContents webContents = mActivityTestRule.getActivity().getCurrentWebContents(); @@ -189,9 +183,6 @@ @Test @MediumTest @Restriction(Restriction.RESTRICTION_TYPE_INTERNET) - @DisableIf.Build( - sdk_is_less_than = Build.VERSION_CODES.Q, - message = "https://crbug.com/1424178") public void testSaveCardInfoBarWithEmptyName() throws TimeoutException { mActivityTestRule.loadUrl(mServer.getURL(TEST_FORM_URL)); final WebContents webContents = mActivityTestRule.getActivity().getCurrentWebContents();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java index bc3e2c0..6c2cd8d1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerTest.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.compositor.layouts; -import static android.os.Build.VERSION_CODES.N_MR1; - import static androidx.test.espresso.matcher.ViewMatchers.assertThat; import static org.hamcrest.Matchers.is; @@ -49,7 +47,6 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Features.DisableFeatures; @@ -440,8 +437,7 @@ @Test @MediumTest - @DisableIf.Build(sdk_is_greater_than = N_MR1, message = "crbug.com/1139943") - @DisabledTest(message = "crbug.com/1216438") // Failures on N. + @DisabledTest(message = "crbug.com/1216438, crbug.com/1139943") public void testLayoutObserverNotification_ShowAndHide_TabSwitcher() throws TimeoutException { LayoutObserverCallbackHelper startedShowingCallback = new LayoutObserverCallbackHelper(); LayoutObserverCallbackHelper finishedShowingCallback = new LayoutObserverCallbackHelper();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java index ec628b7..451772e9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRelatedSearchesTest.java
@@ -6,8 +6,6 @@ import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; -import android.os.Build; - import androidx.test.filters.SmallTest; import org.hamcrest.Matchers; @@ -24,7 +22,6 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -140,7 +137,6 @@ @Test @SmallTest - @MinAndroidSdkLevel(Build.VERSION_CODES.Q) // Run on Android 10 (API 29) and newer @Feature({"ContextualSearch"}) public void testRelatedSearchesInBarWithDefaultQuery_HighlightDefaultQuery() throws Exception { ContextualSearchFakeServer.FakeResolveSearch fakeSearch =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java index 3a924df..304894a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityAppMenuTest.java
@@ -22,7 +22,6 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.View; @@ -128,10 +127,8 @@ @Override public Object getSystemService(String name) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { - if (name.equals(Context.SHORTCUT_SERVICE)) { - return null; - } + if (name.equals(Context.SHORTCUT_SERVICE)) { + return null; } return super.getSystemService(name); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index fa02200..bbdedb7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -2224,7 +2224,6 @@ @SmallTest @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) @EnableFeatures({ChromeFeatureList.CCT_RESIZABLE_FOR_THIRD_PARTIES}) - @MinAndroidSdkLevel(Build.VERSION_CODES.O_MR1) // crbug.com/350394860 @DisableIf.Device(DeviceFormFactor.ONLY_TABLET) public void testLaunchPartialCustomTabActivity_SideSheet() throws Exception { @@ -2281,7 +2280,6 @@ @EnableFeatures({ChromeFeatureList.CCT_RESIZABLE_FOR_THIRD_PARTIES}) // Screen rotation is not relevant on automotive. @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) - @MinAndroidSdkLevel(Build.VERSION_CODES.O_MR1) // Bug in O that's been fixed in 8.1 // https://issuetracker.google.com/issues/68427483 public void testLaunchPartialCustomTabActivity_Transition() throws Exception {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java index eb7a8f967..b62762f9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
@@ -260,10 +260,6 @@ @Test @SmallTest @DisableIf.Build( - supported_abis_includes = "x86", - sdk_equals = VERSION_CODES.P, - message = "crbug.com/1188920") - @DisableIf.Build( supported_abis_includes = "x86_64", sdk_is_less_than = VERSION_CODES.TIRAMISU, message = "crbug.com/1188920")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java index f101f2a6..918e3f6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/desktop_windowing/AppHeaderCoordinatorBrowserTest.java
@@ -608,7 +608,8 @@ new AppHeaderState( mWindowRect, mWidestUnoccludedRect, isInDesktopWindow); ((AppHeaderCoordinator) appHeaderStateProvider) - .setStateForTesting(isInDesktopWindow, appHeaderState); + .setStateForTesting( + isInDesktopWindow, appHeaderState, /* isFocused= */ true); AppHeaderUtils.setAppInDesktopWindowForTesting(isInDesktopWindow); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java index 5f09e47..7fa966a2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.display_cutout; -import android.os.Build; import android.os.Build.VERSION_CODES; import android.view.WindowManager; @@ -21,7 +20,6 @@ import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Features; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.blink.mojom.ViewportFit; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -41,7 +39,6 @@ ChromeFeatureList.DRAW_CUTOUT_EDGE_TO_EDGE, ChromeFeatureList.EDGE_TO_EDGE_BOTTOM_CHIN }) -@MinAndroidSdkLevel(Build.VERSION_CODES.P) public class DisplayCutoutTest { @Rule public DisplayCutoutTestRule mTestRule = new DisplayCutoutTestRule<>(ChromeActivity.class);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java index 8ddbfff..b597541c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTestRule.java
@@ -5,10 +5,8 @@ package org.chromium.chrome.browser.display_cutout; import android.graphics.Rect; -import android.os.Build; import android.view.WindowManager.LayoutParams; -import androidx.annotation.RequiresApi; import androidx.test.platform.app.InstrumentationRegistry; import org.hamcrest.Matchers; @@ -42,7 +40,6 @@ * * @param <T> The type of {@link ChromeActivity} to use for the test. */ -@RequiresApi(Build.VERSION_CODES.P) public class DisplayCutoutTestRule<T extends ChromeActivity> extends ChromeActivityTestRule<T> { /** These are the two test safe areas with and without the test cutout. */ public static final Rect TEST_SAFE_AREA_WITH_CUTOUT = new Rect(10, 20, 30, 40);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java index 29b866e..2a9d29e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.display_cutout; -import android.os.Build; import android.view.WindowManager; import androidx.test.filters.LargeTest; @@ -15,7 +14,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.blink.mojom.DisplayMode; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -25,7 +23,6 @@ /** Tests the display cutout on a WebApp. */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@MinAndroidSdkLevel(Build.VERSION_CODES.P) public class WebappDisplayCutoutTest { @Rule public WebappDisplayCutoutTestRule mTestRule = new WebappDisplayCutoutTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTestRule.java index 603adcb..b4d1d8c2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTestRule.java
@@ -6,9 +6,7 @@ import android.content.Intent; import android.net.Uri; -import android.os.Build; -import androidx.annotation.RequiresApi; import androidx.test.core.app.ApplicationProvider; import androidx.test.platform.app.InstrumentationRegistry; @@ -28,7 +26,6 @@ import java.lang.annotation.Target; /** Custom test rule for simulating a {@link WebappActivity} with a Display Cutout. */ -@RequiresApi(Build.VERSION_CODES.P) public class WebappDisplayCutoutTestRule extends DisplayCutoutTestRule<WebappActivity> { /** Test data for the test webapp. */ private static final String WEBAPP_ID = "webapp_id";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java index 74d3a391..d9509da 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadTestRule.java
@@ -8,7 +8,6 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; -import android.os.Build; import android.os.Environment; import android.text.TextUtils; @@ -309,17 +308,7 @@ } private void deleteFile(String fileName) { - // Delete file path on pre Q. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - final File fileToDelete = new File(DOWNLOAD_DIRECTORY, fileName); - if (fileToDelete.exists()) { - Assert.assertTrue( - "Could not delete file that would block this test", fileToDelete.delete()); - } - return; - } - - // Delete content URI starting from Q. + // Delete content URI. Uri uri = DownloadCollectionBridge.getDownloadUriForFileName(fileName); if (uri == null) { Log.e(TAG, "Can't find URI of file for deletion: %s on Android P+.", fileName);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java index a73b766..fcbe451 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/PictureInPictureActivityTest.java
@@ -19,12 +19,10 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; -import android.os.Build; import android.os.Bundle; import android.util.Rational; import android.view.View; -import androidx.annotation.RequiresApi; import androidx.lifecycle.Lifecycle; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -47,7 +45,6 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; @@ -70,7 +67,6 @@ @Batch(Batch.PER_CLASS) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) -@RequiresApi(Build.VERSION_CODES.O) public class PictureInPictureActivityTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @@ -127,7 +123,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testStartActivity() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -139,7 +134,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testExitOnClose() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); testExitOn(activity, () -> activity.close()); @@ -147,7 +141,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testExitOnCrash() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); testExitOn(activity, () -> WebContentsUtils.simulateRendererKilled(getWebContents())); @@ -156,7 +149,6 @@ @Test @MediumTest @DisabledTest(message = "b/353025645") - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testMakeEnterPictureInPictureWithBadSourceRect() throws Throwable { mSourceRectHint.left = -1; @@ -168,7 +160,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testExitOnBackToTab() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -183,7 +174,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testResize() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -203,7 +193,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testMediaActions() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -253,7 +242,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testMediaActionsForVideoConferencing() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -279,7 +267,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testMediaActionsForTrackControl() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -301,7 +288,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testMediaActionsForSlideControl() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -323,7 +309,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testActionsInSync() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -371,7 +356,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testNotifyNativeWhenTabClose() throws Throwable { PictureInPictureActivity activity = startPictureInPictureActivity(); @@ -381,7 +365,6 @@ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE) public void testPipWindowExitsIfTokenDoesNotExist() throws Throwable { // If the window token doesn't produce a native window, then the activity should exit.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/FullscreenVideoPictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/FullscreenVideoPictureInPictureControllerTest.java index 54dbb35..0931d821 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/FullscreenVideoPictureInPictureControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/FullscreenVideoPictureInPictureControllerTest.java
@@ -6,9 +6,6 @@ import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; -import android.os.Build; - -import androidx.annotation.RequiresApi; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -23,7 +20,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -52,7 +48,6 @@ RESTRICTION_TYPE_NON_LOW_END_DEVICE, DeviceRestriction.RESTRICTION_TYPE_NON_AUTO // PiP not supported on AAOS. }) -@RequiresApi(Build.VERSION_CODES.O) public class FullscreenVideoPictureInPictureControllerTest { // TODO(peconn): Add a test for exit on Tab Reparenting. private static final String TEST_PATH = "/chrome/test/data/media/bigbuck-player.html"; @@ -73,7 +68,6 @@ /** Tests that we can detect when a video is playing fullscreen, a prerequisite for PiP. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testFullscreenVideoDetected() throws Throwable { enterFullscreen(); } @@ -81,7 +75,6 @@ /** Tests that fullscreen detection only applies to playing videos. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/335305496") public void testFullscreenVideoDetectedOnlyWhenPlaying() throws Throwable { enterFullscreen(); @@ -93,7 +86,6 @@ /** Tests that we can enter PiP. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/339501283") public void testEnterPip() throws Throwable { enterFullscreen(); @@ -110,7 +102,6 @@ /** Tests that PiP is left when we navigate the main page. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/1211930/") public void testExitPipOnNavigation() throws Throwable { testExitOn( @@ -123,7 +114,6 @@ /** Tests that PiP is left when the video leaves fullscreen. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/348618570") public void testExitOnLeaveFullscreen() throws Throwable { testExitOn(() -> DOMUtils.exitFullscreen(getWebContents())); @@ -132,7 +122,6 @@ /** Tests that PiP is left when the active Tab is closed. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "b/354013006") public void testExitOnCloseTab() throws Throwable { // We want 2 Tabs so we can close the first without any special behaviour. @@ -144,7 +133,6 @@ /** Tests that PiP is left when the renderer crashes. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testExitOnCrash() throws Throwable { testExitOn(() -> WebContentsUtils.simulateRendererKilled(getWebContents())); } @@ -152,7 +140,6 @@ /** Tests that PiP is left when a new Tab is created in the foreground. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/1429112") public void testExitOnNewForegroundTab() throws Throwable { testExitOn( @@ -176,7 +163,6 @@ */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/1211930/#c10") public void testNoExitOnIframeNavigation() throws Throwable { // Add a TabObserver so we know when the iFrame navigation has occurred before we check that @@ -203,7 +189,6 @@ /** Tests that we can resume PiP after it has been cancelled. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/1429112") public void testReenterPip() throws Throwable { enterFullscreen(); @@ -282,7 +267,6 @@ /** Tests that we exit PiP whe device is locked. */ @Test @MediumTest - @MinAndroidSdkLevel(Build.VERSION_CODES.O) @DisabledTest(message = "https://crbug.com/335422062") public void testExitPipWhenDeviceLocked() throws Throwable { AsyncInitializationActivity.interceptMoveTaskToBackForTesting();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java index 4306d82f..07d1d68 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridgeTest.java
@@ -740,7 +740,6 @@ @LargeTest @Feature({"Browser", "Notifications"}) @Features.EnableFeatures(ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testNotificationProvisionalUnsubscribeAndCommit() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( ContentSettingValues.ALLOW, mPermissionTestRule.getOrigin()); @@ -790,7 +789,6 @@ @LargeTest @Feature({"Browser", "Notifications"}) @Features.EnableFeatures(ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testNotificationProvisionalUnsubscribeAndUndo() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( ContentSettingValues.ALLOW, mPermissionTestRule.getOrigin()); @@ -866,7 +864,6 @@ @Feature({"Browser", "Notifications"}) @Features.EnableFeatures( ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE + ":use_service_intent/true") - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testNotificationProvisionalUnsubscribeWithServiceIntent() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( ContentSettingValues.ALLOW, mPermissionTestRule.getOrigin()); @@ -1050,7 +1047,6 @@ ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testNotificationShowWarningNotificationsThenDismissAndUnsubscribe() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( @@ -1175,7 +1171,6 @@ ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testNotificationShowWarningNotificationThenShowNotificationThenAlwaysAllow() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( @@ -1285,7 +1280,6 @@ ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testShowWarningFeatureDoesNotWarnForUnsuspiciousNotification() throws Exception { mNotificationTestRule.setNotificationContentSettingForOrigin( ContentSettingValues.ALLOW, mPermissionTestRule.getOrigin()); @@ -1356,7 +1350,6 @@ ChromeFeatureList.NOTIFICATION_ONE_TAP_UNSUBSCRIBE, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testShowWarningFeatureSwitchButtons() throws Exception { FeatureOverrides.overrideParam( ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS, @@ -1430,7 +1423,6 @@ ChromeFeatureList.REPORT_NOTIFICATION_CONTENT_DETECTION_DATA, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testReportAsSafe() throws Exception { var histogramWatcher = HistogramWatcher.newBuilder() @@ -1513,7 +1505,6 @@ ChromeFeatureList.REPORT_NOTIFICATION_CONTENT_DETECTION_DATA, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testReportWarnedNotificationAsSpam() throws Exception { var histogramWatcher = HistogramWatcher.newBuilder() @@ -1604,7 +1595,6 @@ ChromeFeatureList.REPORT_NOTIFICATION_CONTENT_DETECTION_DATA, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testReportUnwarnedNotificationAsSpam() throws Exception { var histogramWatcher = HistogramWatcher.newBuilder() @@ -1678,7 +1668,6 @@ ChromeFeatureList.REPORT_NOTIFICATION_CONTENT_DETECTION_DATA, ChromeFeatureList.SHOW_WARNINGS_FOR_SUSPICIOUS_NOTIFICATIONS }) - @MinAndroidSdkLevel(Build.VERSION_CODES.P) public void testReportOptionNotAvailableIfNoOriginalShown() throws Exception { var histogramWatcher = HistogramWatcher.newBuilder()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java index 60fcd52..a742d35c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -283,7 +283,6 @@ @Test @SmallTest @Feature({"NewTabPage", "FeedNewTabPage"}) - @DisableIf.Build(sdk_equals = Build.VERSION_CODES.P, message = "http://crbug.com/40664848") @DisableIf.Build(sdk_equals = Build.VERSION_CODES.R, message = "http://crbug.com/40664848") public void testFocusFakebox() { int initialFakeboxTop = getFakeboxTop(mNtp);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridgeTest.java index 34c22c9..708bcd7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridgeTest.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.offlinepages; -import android.os.Build; - import androidx.test.filters.SmallTest; import org.junit.Assert; @@ -21,8 +19,6 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.MaxAndroidSdkLevel; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageModelObserver; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.SavePageCallback; @@ -103,70 +99,12 @@ mTestUrl = mActivityTestRule.getTestServer().getURL(TEST_PAGE); } - @Test - @SmallTest - @MaxAndroidSdkLevel( - value = Build.VERSION_CODES.P, - reason = - "On Android Q+, publish offline pages to the downloads collection " - + "rather than DownloadManager.") - public void testAddCompletedDownload() throws InterruptedException, TimeoutException { - Assert.assertTrue(OfflinePageArchivePublisherBridge.isAndroidDownloadManagerInstalled()); - - WebPageStation webPage = - mActivityTestRule.startOnBlankPage().loadWebPageProgrammatically(mTestUrl); - savePage(TEST_CLIENT_ID, webPage); - OfflinePageItem page = OfflineTestUtil.getAllPages().get(0); - - long downloadId = - OfflinePageArchivePublisherBridge.addCompletedDownload( - page.getTitle(), - "description", - page.getFilePath(), - page.getFileSize(), - page.getUrl(), - ""); - - Assert.assertNotEquals(0L, downloadId); - } - - @Test - @SmallTest - @MaxAndroidSdkLevel( - value = Build.VERSION_CODES.P, - reason = - "On Android Q+, publish offline pages to the downloads collection " - + "rather than DownloadManager.") - public void testRemove() throws InterruptedException, TimeoutException { - Assert.assertTrue(OfflinePageArchivePublisherBridge.isAndroidDownloadManagerInstalled()); - - WebPageStation webPage = - mActivityTestRule.startOnBlankPage().loadWebPageProgrammatically(mTestUrl); - savePage(TEST_CLIENT_ID, webPage); - OfflinePageItem page = OfflineTestUtil.getAllPages().get(0); - - long downloadId = - OfflinePageArchivePublisherBridge.addCompletedDownload( - page.getTitle(), - "description", - page.getFilePath(), - page.getFileSize(), - page.getUrl(), - ""); - - Assert.assertNotEquals(0L, downloadId); - - long[] ids = new long[] {downloadId}; - Assert.assertEquals(1, OfflinePageArchivePublisherBridge.remove(ids)); - } - /** * TODO(crbug.com/40683443): This test fails on Android Q/10 (SDK 29). Leaving it enabled for * now as there's currently no bot running tests with that OS version. */ @Test @SmallTest - @MinAndroidSdkLevel(29) @DisabledTest(message = "https://crbug.com/1068408") public void testPublishArchiveToDownloadsCollection() throws InterruptedException, TimeoutException { @@ -192,7 +130,6 @@ */ @Test @SmallTest - @MinAndroidSdkLevel(29) @DisabledTest(message = "https://crbug.com/1068408") public void testPublishArchiveToDownloadsCollection_NoCrashWhenAndroidCantGenerateUniqueFilename()
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java index a6e7937..5cec631a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.offlinepages; -import android.net.Uri; -import android.os.Build.VERSION_CODES; import android.util.Base64; import androidx.test.filters.MediumTest; @@ -24,8 +22,6 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.MaxAndroidSdkLevel; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.OfflinePageModelObserver; import org.chromium.chrome.browser.offlinepages.OfflinePageBridge.SavePageCallback; @@ -43,11 +39,6 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.net.NetworkChangeNotifier; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -447,9 +438,6 @@ @Test @MediumTest - @MinAndroidSdkLevel( - value = VERSION_CODES.Q, - reason = "OfflinePage File Path is content uri on Q+") // TODO: expand this test to match testGetLoadUrlParamsForOpeningMhtmlFileUrl_File. public void testGetLoadUrlParamsForOpeningMhtmlFileUrl_ContentUri() throws Exception { mActivityTestRule.loadUrl(mTestUrl); @@ -478,81 +466,6 @@ -1, extraHeaders.indexOf("id=" + Long.toString(offlinePage.getOfflineId()))); } - @Test - @MediumTest - @MaxAndroidSdkLevel( - value = VERSION_CODES.P, - reason = "OfflinePage File Path is content uri on Q+") - public void testGetLoadUrlParamsForOpeningMhtmlFileUrl_File() throws Exception { - mActivityTestRule.loadUrl(mTestUrl); - savePage(SavePageResult.SUCCESS, mTestUrl); - List<OfflinePageItem> allPages = OfflineTestUtil.getAllPages(); - Assert.assertEquals(1, allPages.size()); - OfflinePageItem offlinePage = allPages.get(0); - File archiveFile = new File(offlinePage.getFilePath()); - - // The file URL pointing to the archive file should be replaced with http/https URL of the - // offline page. - String fileUrl = Uri.fromFile(archiveFile).toString(); - LoadUrlParams loadUrlParams = getLoadUrlParamsForOpeningMhtmlFileOrContent(fileUrl); - Assert.assertEquals(offlinePage.getUrl(), loadUrlParams.getUrl()); - String extraHeaders = loadUrlParams.getVerbatimHeaders(); - Assert.assertNotNull(extraHeaders); - Assert.assertNotEquals(-1, extraHeaders.indexOf("reason=file_url_intent")); - Assert.assertNotEquals( - "intent_url field not found in header: " + extraHeaders, - -1, - extraHeaders.indexOf( - "intent_url=" - + Base64.encodeToString( - ApiCompatibilityUtils.getBytesUtf8(fileUrl), - Base64.NO_WRAP))); - Assert.assertNotEquals( - -1, extraHeaders.indexOf("id=" + Long.toString(offlinePage.getOfflineId()))); - - // Make a copy of the original archive file. - File tempFile = File.createTempFile("Test", ""); - copyFile(archiveFile, tempFile); - - // The file URL pointing to file copy should also be replaced with http/https URL of the - // offline page. - String tempFileUrl = Uri.fromFile(tempFile).toString(); - loadUrlParams = getLoadUrlParamsForOpeningMhtmlFileOrContent(tempFileUrl); - Assert.assertEquals(offlinePage.getUrl(), loadUrlParams.getUrl()); - extraHeaders = loadUrlParams.getVerbatimHeaders(); - Assert.assertNotNull(extraHeaders); - Assert.assertNotEquals( - "reason field not found in header: " + extraHeaders, - -1, - extraHeaders.indexOf("reason=file_url_intent")); - Assert.assertNotEquals( - "intent_url field not found in header: " + extraHeaders, - -1, - extraHeaders.indexOf( - "intent_url=" - + Base64.encodeToString( - ApiCompatibilityUtils.getBytesUtf8(tempFileUrl), - Base64.NO_WRAP))); - Assert.assertNotEquals( - "id field not found in header: " + extraHeaders, - -1, - extraHeaders.indexOf("id=" + Long.toString(offlinePage.getOfflineId()))); - - // Modify the copied file. - FileChannel tempFileChannel = new FileOutputStream(tempFile, true).getChannel(); - tempFileChannel.truncate(10); - tempFileChannel.close(); - - // The file URL pointing to modified file copy should still get the file URL. - loadUrlParams = getLoadUrlParamsForOpeningMhtmlFileOrContent(tempFileUrl); - Assert.assertEquals(tempFileUrl, loadUrlParams.getUrl()); - extraHeaders = loadUrlParams.getVerbatimHeaders(); - Assert.assertNull(extraHeaders); - - // Cleans up. - Assert.assertTrue(tempFile.delete()); - } - // Returns offline ID. private long savePage(final int expectedResult, final String expectedUrl) throws InterruptedException { @@ -688,17 +601,4 @@ Assert.assertTrue(semaphore.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); return ref.get(); } - - private static void copyFile(File source, File dest) throws IOException { - FileChannel inputChannel = null; - FileChannel outputChannel = null; - try { - inputChannel = new FileInputStream(source).getChannel(); - outputChannel = new FileOutputStream(dest).getChannel(); - outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); - } finally { - inputChannel.close(); - outputChannel.close(); - } - } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/VirtualViewStructureInstrumentationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/VirtualViewStructureInstrumentationTest.java index 0916e2a5..a0ff5844 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/VirtualViewStructureInstrumentationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/VirtualViewStructureInstrumentationTest.java
@@ -16,7 +16,6 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.transit.ChromeTransitTestRules; @@ -44,7 +43,6 @@ @Test @SmallTest - @MinAndroidSdkLevel(value = 28) @EnableFeatures({AutofillFeatures.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID}) @DisabledTest(message = "https://crbug.com/414988519") public void testLogs3PModeDisabledMetrics() { @@ -67,7 +65,6 @@ @Test @SmallTest - @MinAndroidSdkLevel(value = 28) @EnableFeatures({AutofillFeatures.AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID}) public void testDoesntLog3PModeDisabledMetricsWhen3PModeEnabled() { WebPageStation page = mActivityTestRule.startOnBlankPage();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/RuntimePermissionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/RuntimePermissionTest.java index 3c394cb1..aa873070 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/RuntimePermissionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/RuntimePermissionTest.java
@@ -5,39 +5,28 @@ package org.chromium.chrome.browser.permissions; import android.Manifest; -import android.os.Build; import androidx.test.filters.MediumTest; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.HistogramWatcher; -import org.chromium.base.test.util.MaxAndroidSdkLevel; -import org.chromium.chrome.browser.download.DownloadItem; -import org.chromium.chrome.browser.download.DownloadManagerService; -import org.chromium.chrome.browser.download.DownloadManagerService.DownloadObserver; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.permissions.RuntimePermissionTestUtils.RuntimePromptResponse; import org.chromium.chrome.browser.permissions.RuntimePermissionTestUtils.TestAndroidPermissionDelegate; -import org.chromium.chrome.browser.profiles.ProfileKey; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.R; -import org.chromium.components.offline_items_collection.ContentId; import org.chromium.components.permissions.DismissalType; import org.chromium.content_public.common.ContentSwitches; import org.chromium.ui.base.DeviceFormFactor; -import java.util.List; - /** Testing the interaction with the runtime permission prompt (Android level prompt). */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @@ -236,58 +225,6 @@ @Test @MediumTest - @Feature({"RuntimePermissions", "Downloads"}) - @MaxAndroidSdkLevel( - value = Build.VERSION_CODES.P, - reason = - "WRITE_EXTERNAL_STORAGE is not supported starting in Android R and Q requires a" - + " workaround") - public void testDenyRuntimeDownload() throws Exception { - DownloadObserver observer = - new DownloadObserver() { - @Override - public void onAllDownloadsRetrieved( - final List<DownloadItem> list, ProfileKey profileKey) {} - - @Override - public void onDownloadItemUpdated(DownloadItem item) {} - - @Override - public void onDownloadItemRemoved(String guid) {} - - @Override - public void onAddOrReplaceDownloadSharedPreferenceEntry(ContentId id) {} - - @Override - public void onDownloadItemCreated(DownloadItem item) { - Assert.assertFalse("Should not have started a download item", true); - } - }; - - ThreadUtils.runOnUiThreadBlocking( - () -> { - DownloadManagerService.getDownloadManagerService() - .addDownloadObserver(observer); - }); - - String[] requestablePermission = new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}; - mTestAndroidPermissionDelegate = - new TestAndroidPermissionDelegate( - requestablePermission, RuntimePromptResponse.DENY); - RuntimePermissionTestUtils.runTest( - mPermissionTestRule, - mTestAndroidPermissionDelegate, - DOWNLOAD_TEST, - /* expectPermissionAllowed= */ false, - /* promptDecision= */ PermissionTestRule.PromptDecision.NONE, - /* waitForMissingPermissionPrompt= */ true, - /* waitForUpdater= */ false, - "document.getElementsByTagName('a')[0].click();", - R.string.missing_storage_permission_download_education_text); - } - - @Test - @MediumTest @Feature({"RuntimePermissions", "Location"}) public void testDenyTriggersNoRuntime() throws Exception { RuntimePermissionTestUtils.setupGeolocationSystemMock();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/FullscreenSigninAndHistorySyncIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/FullscreenSigninAndHistorySyncIntegrationTest.java index e8ead2a..0891883 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/FullscreenSigninAndHistorySyncIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/FullscreenSigninAndHistorySyncIntegrationTest.java
@@ -28,7 +28,6 @@ import android.content.Intent; import android.content.res.Configuration; import android.graphics.drawable.ColorDrawable; -import android.os.Build; import android.widget.ProgressBar; import androidx.test.core.app.ApplicationProvider; @@ -54,7 +53,6 @@ import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.HistogramWatcher; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -469,9 +467,6 @@ @Test @MediumTest - // There is an issue causing {@link Activity.setRequestedOrientation} to throw an exception in - // Android 8 which was fixed in Android 8.1. See b/70718000 for example. - @MinAndroidSdkLevel(Build.VERSION_CODES.O_MR1) @Restriction(DeviceRestriction.RESTRICTION_TYPE_NON_AUTO) public void testScreenRotation() { when(mHistorySyncHelperMock.shouldSuppressHistorySync()).thenReturn(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettingsTest.java index c2ea983..414add6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettingsTest.java
@@ -11,8 +11,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import android.os.Build; - import androidx.test.filters.LargeTest; import org.junit.After; @@ -32,7 +30,6 @@ import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; @@ -230,9 +227,6 @@ @Test @LargeTest - @MinAndroidSdkLevel( - value = Build.VERSION_CODES.Q, - reason = "Digital Wellbeing is only available from Q.") public void testUsageStatsReportingShown() { ThreadUtils.runOnUiThreadBlocking( () -> { @@ -254,9 +248,6 @@ @Test @LargeTest - @MinAndroidSdkLevel( - value = Build.VERSION_CODES.Q, - reason = "Digital Wellbeing is only available from Q.") public void testUsageStatsReportingNotShown() { ThreadUtils.runOnUiThreadBlocking( () -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerTest.java index 62498458..f5acd4a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabbed_mode/TabbedNavigationBarColorControllerTest.java
@@ -23,7 +23,6 @@ import android.view.Window; import androidx.annotation.ColorInt; -import androidx.annotation.RequiresApi; import androidx.core.graphics.ColorUtils; import androidx.test.filters.MediumTest; import androidx.test.filters.SmallTest; @@ -80,8 +79,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Features.DisableFeatures({ChromeFeatureList.EDGE_TO_EDGE_EVERYWHERE}) -@MinAndroidSdkLevel(Build.VERSION_CODES.O_MR1) -@RequiresApi(Build.VERSION_CODES.O_MR1) @SuppressLint("NewApi") public class TabbedNavigationBarColorControllerTest { @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java index 877a3deb..7f459a3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
@@ -615,7 +615,6 @@ @Test @LargeTest - @DisableIf.Build(sdk_is_less_than = VERSION_CODES.P) @DisableIf.Device(DeviceFormFactor.ONLY_TABLET) // https://crbug.com/338997261 public void testMergeOnMultiDisplay_CTA_Resumed_CTA2_Not_Resumed() throws TimeoutException { ThreadUtils.runOnUiThreadBlocking( @@ -667,7 +666,6 @@ @Test @LargeTest - @DisableIf.Build(sdk_is_less_than = VERSION_CODES.P) @DisableIf.Device(DeviceFormFactor.ONLY_TABLET) // https://crbug.com/338997261 public void testMergeOnMultiDisplay_OnDisplayChanged() throws TimeoutException { ThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index e240165e..21bc8a3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -47,7 +47,6 @@ import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.Matchers; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.app.metrics.LaunchCauseMetrics; import org.chromium.chrome.browser.app.tabmodel.AsyncTabParamsManagerSingleton; @@ -1422,7 +1421,6 @@ @Test @SmallTest @Feature({"TabPersistentStore", "MultiWindow"}) - @MinAndroidSdkLevel(24) public void testDuplicateTabIdsOnColdStart() throws Exception { final TabModelMetaDataInfo info = TestTabModelDirectory.TAB_MODEL_METADATA_V5_NO_M18;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java index 8568a24f..15cd4d07 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -29,7 +29,6 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisableIf; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.browser.ChromeTabbedActivity2; @@ -368,7 +367,6 @@ @MediumTest @DisableIf.Device(DeviceFormFactor.ONLY_TABLET) // https://crbug.com/338997949 @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.R) // https://crbug.com/1297370 - @MinAndroidSdkLevel(24) @CommandLineFlags.Add(ChromeSwitches.DISABLE_TAB_MERGING_FOR_TESTING) public void testOpenRecentlyClosedTabMultiWindowFallback() throws TimeoutException { final ChromeTabbedActivity2 secondActivity =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/WebAppHeaderLayoutBrowserTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/WebAppHeaderLayoutBrowserTest.java index b3caef1..3f208bb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ui/WebAppHeaderLayoutBrowserTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ui/WebAppHeaderLayoutBrowserTest.java
@@ -246,7 +246,8 @@ new AppHeaderState( mWindowRect, mWidestUnoccludedRect, isInDesktopWindow); ((AppHeaderCoordinator) appHeaderStateProvider) - .setStateForTesting(isInDesktopWindow, appHeaderState); + .setStateForTesting( + isInDesktopWindow, appHeaderState, /* isFocused= */ true); AppHeaderUtils.setAppInDesktopWindowForTesting(isInDesktopWindow); }); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java index 698e358..403e5072 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java
@@ -7,8 +7,6 @@ import static org.chromium.chrome.browser.vr.WebXrArTestFramework.PAGE_LOAD_TIMEOUT_S; import static org.chromium.chrome.browser.vr.XrTestFramework.POLL_TIMEOUT_SHORT_MS; -import android.os.Build; - import androidx.test.filters.MediumTest; import org.junit.Before; @@ -22,7 +20,6 @@ import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.vr.rules.ArPlaybackFile; import org.chromium.chrome.browser.vr.rules.XrActivityRestriction; @@ -36,8 +33,6 @@ /** End-to-end tests for testing WebXR for AR's camera access behavior. */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -// TODO(crbug.com/40709670) Change this to Build.VERSION_CODES.N once N support is added. -@MinAndroidSdkLevel(Build.VERSION_CODES.O) public class WebXrArCameraAccessTest { @ClassParameter private static final List<ParameterSet> sClassParams =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenAddShortcutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenAddShortcutTest.java index 6dedd77..f5e526d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenAddShortcutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/AddToHomescreenAddShortcutTest.java
@@ -7,7 +7,6 @@ import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; -import android.os.Build; import android.os.Handler; import android.text.TextUtils; @@ -26,7 +25,6 @@ import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.browser.ShortcutHelper; @@ -248,7 +246,6 @@ @Test @SmallTest @Feature("{Webapp}") - @MinAndroidSdkLevel(Build.VERSION_CODES.O) public void testAddAdaptableShortcut() throws Exception { // Test the baseline of no adaptive icon. loadUrl(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java index d6c609b..65bc5704 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillLocalCardEditorTest.java
@@ -93,7 +93,7 @@ /* name= */ "John Doe", /* number= */ NON_AMEX_CARD_NUMBER, /* networkAndLastFourDigits= */ "", - /* month= */ "5", + /* month= */ "05", AutofillTestHelper.nextYear(), /* basicCardIssuerNetwork= */ "visa", /* issuerIconDrawableId= */ 0, @@ -111,7 +111,7 @@ /* name= */ "John Doe", /* number= */ NON_AMEX_CARD_NUMBER, /* networkAndLastFourDigits= */ "", - /* month= */ "5", + /* month= */ "05", AutofillTestHelper.nextYear(), /* basicCardIssuerNetwork= */ "visa", /* issuerIconDrawableId= */ 0, @@ -141,7 +141,7 @@ /* name= */ "John Doe", /* number= */ AMEX_CARD_NUMBER, /* networkAndLastFourDigits= */ "", - /* month= */ "5", + /* month= */ "05", AutofillTestHelper.nextYear(), /* basicCardIssuerNetwork= */ "amex", /* issuerIconDrawableId= */ 0, @@ -322,7 +322,7 @@ initFragment(getSampleLocalCard()); assertThat(mNicknameText.getText().toString()).isEmpty(); - assertFalse(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -334,8 +334,7 @@ initFragment(card); assertThat(mNicknameText.getText().toString()).isEqualTo(nickname); - // If the nickname is not modified `mDoneButton` button should be disabled. - assertFalse(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -354,8 +353,8 @@ mNicknameText.setText("Nickname 123"); assertThat(mNicknameLabel.getError()).isEqualTo(mNicknameInvalidError); - // Since the nickname has an error, the done button should be disabled. - assertFalse(mDoneButton.isEnabled()); + // Since the nickname has an error, the form should not be valid. + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -371,7 +370,7 @@ // Set the nickname to valid one. mNicknameText.setText("Valid Nickname"); assertThat(mNicknameLabel.getError()).isNull(); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -388,7 +387,7 @@ mNicknameText.setText(null); assertThat(mNicknameLabel.getError()).isNull(); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -446,7 +445,7 @@ initFragment(card); assertThat(mCvc.getText().toString()).isEqualTo(cvc); - assertFalse(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -529,7 +528,7 @@ .isEqualTo( String.format( "%s/%s", validExpirationMonth, validExpirationYear.substring(2))); - assertFalse(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -543,7 +542,7 @@ String.format("%s/%s", invalidExpirationMonth, validExpirationYear.substring(2))); assertThat(mExpirationDate.getError()).isEqualTo(mExpirationDateInvalidError); - assertFalse(mDoneButton.isEnabled()); + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -558,7 +557,7 @@ "%s/%s", validExpirationMonth, invalidPastExpirationYear.substring(2))); assertThat(mExpirationDate.getError()).isEqualTo(mExpiredCardError); - assertFalse(mDoneButton.isEnabled()); + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -574,13 +573,13 @@ initFragment(card); assertThat(mExpirationDate.getError()).isEqualTo(mExpiredCardError); - assertFalse(mDoneButton.isEnabled()); + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); mExpirationDate.setText( String.format("%s/%s", validExpirationMonth, validExpirationYear.substring(2))); assertThat(mExpirationDate.getError()).isNull(); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); } @Test @@ -594,13 +593,13 @@ String.format("%s/%s", validExpirationMonth, validExpirationYear.substring(2))); assertThat(mExpirationDate.getError()).isNull(); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); mExpirationDate.setText( String.format("%s/%s", validExpirationMonth, /* expiration year */ "")); - // Button should be disabled, but no error should be visible too. - assertFalse(mDoneButton.isEnabled()); + // Empty expiration date should make the form invalid. + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); assertThat(mDoneButton.getError()).isNull(); } @@ -615,12 +614,12 @@ String.format("%s/%s", validExpirationMonth, validExpirationYear.substring(2))); assertThat(mExpirationDate.getError()).isNull(); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); mExpirationDate.setText(/* date= */ ""); - // Button should be disabled, but no error should be visible too. - assertFalse(mDoneButton.isEnabled()); + // Clearing the expiration data should make the form invalid. + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); assertThat(mDoneButton.getError()).isNull(); } @@ -639,21 +638,21 @@ String.format("%s/%s", validExpirationMonth, validExpirationYear.substring(2))); mNicknameText.setText(validNickname); - assertTrue(mDoneButton.isEnabled()); + assertTrue(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); mExpirationDate.setText( String.format( "%s/%s", validExpirationMonth, invalidPastExpirationYear.substring(2))); mNicknameText.setText(invalidNickname); - // Button should be disabled, but no error should be visible too. - assertFalse(mDoneButton.isEnabled()); + // Invalid nickname and expiration year should make the form invalid. + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); assertThat(mDoneButton.getError()).isNull(); mNicknameText.setText(validNickname); - // Button should be disabled, but no error should be visible too. - assertFalse(mDoneButton.isEnabled()); + // Invalid expiration year keeps the form invalid. + assertFalse(mCardEditor.validateFormAndUpdateErrorAndFocusErrorField()); assertThat(mDoneButton.getError()).isNull(); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehaviorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehaviorUnitTest.java index fc91109..69a70c9 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehaviorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CustomTabAdaptiveToolbarBehaviorUnitTest.java
@@ -118,7 +118,7 @@ } @Test - public void registerPerSurfaceButtons_DoesNotAddOpenInBrowser_WhenOpenInBrowserButtonEnabled() { + public void registerPerSurfaceButtons_OpenInBrowser_WhenOpenInBrowserButtonOn() { AdaptiveToolbarButtonController controller = Mockito.mock(AdaptiveToolbarButtonController.class); Supplier<Tracker> trackerSupplier = Mockito.mock(Supplier.class); @@ -129,7 +129,7 @@ when(mIntentDataProvider.getOpenInBrowserButtonState()) .thenReturn(OPEN_IN_BROWSER_STATE_ON); mBehavior.registerPerSurfaceButtons(controller, trackerSupplier); - verify(controller, never()) + verify(controller) .addButtonVariant(eq(AdaptiveToolbarButtonVariant.OPEN_IN_BROWSER), any()); } @@ -179,13 +179,14 @@ @Test @EnableFeatures( - ChromeFeatureList.CCT_ADAPTIVE_BUTTON + ":open_in_browser/true/contextual_only/true") + ChromeFeatureList.CCT_ADAPTIVE_BUTTON + + ":open_in_browser/true/contextual_only/true/default_variant/15") public void resultFilter_skipStaticActionOpenInBrowserCpaMode() { List<Integer> segmentationResults = List.of(OPEN_IN_BROWSER, TRANSLATE); when(mIntentDataProvider.getOpenInBrowserButtonState()) .thenReturn(OPEN_IN_BROWSER_STATE_ON); - assertEquals(UNKNOWN, mBehavior.resultFilter(segmentationResults)); + assertEquals(OPEN_IN_BROWSER, mBehavior.resultFilter(segmentationResults)); when(mIntentDataProvider.getOpenInBrowserButtonState()) .thenReturn(OPEN_IN_BROWSER_STATE_OFF); @@ -232,4 +233,24 @@ when(mIntentDataProvider.getShareButtonState()).thenReturn(SHARE_STATE_OFF); assertFalse(mBehavior.canShowManualOverride(SHARE)); } + + @Test + @EnableFeatures( + ChromeFeatureList.CCT_ADAPTIVE_BUTTON + ":open_in_browser/true/default_variant/15") + public void hideDefaultVariant() { + // Initialize custom action button types. + CustomButtonParams openInBrowser = Mockito.mock(CustomButtonParams.class); + when(openInBrowser.getType()).thenReturn(ButtonType.CCT_OPEN_IN_BROWSER_BUTTON); + + assertEquals( + "The default should be OPEN_IN_BROWSER", + OPEN_IN_BROWSER, + mBehavior.getSegmentationDefault()); + + initBehavior(List.of(openInBrowser)); + assertEquals( + "The default should be UNKNOWN after dedup", + UNKNOWN, + mBehavior.getSegmentationDefault()); + } }
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsForS.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsForS.java index 1bb4d577..4a4045b 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsForS.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/h2o/SplashUtilsForS.java
@@ -80,7 +80,6 @@ * Activity bounds, so to make sure that the screen doesn't change between the shell and Chrome, * we provide a screenshot without the areas normally covered by the status and navigation bar. */ - @RequiresApi(api = VERSION_CODES.Q) private static Bitmap screenshotSplashScreenView( View splashView, View iconView, Insets insets, int backgroundColor, int maxSizeBytes) { int width = splashView.getWidth() - insets.right - insets.left;
diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp index 4f6dc73..ba48595 100644 --- a/chrome/app/settings_chromium_strings.grdp +++ b/chrome/app/settings_chromium_strings.grdp
@@ -121,13 +121,9 @@ </if> <!-- Delete Browsing Data --> - <!-- TODO(crbug.com/397187800): Make DBDv2 strings translatable. --> - <message name="IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL" desc="Sub-label for the 'Manage other Data' row in the 'Delete Browsing Data' dialog, explaining to the user that passwords can only be deleted outside of Chromium." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL" desc="Sub-label for the 'Manage other Data' subpage entrypoint in the 'Delete Browsing Data' dialog, explaining to the user that passwords can only be deleted outside of Chromium."> Passwords can only be deleted outside Chromium </message> - <message name="IDS_SETTINGS_OTHER_DATA_DESCRIPTION" desc="Description text at the top of the 'Other data' subpage." translateable="false"> - This data is managed outside Chromium. To delete it, go to its management settings. - </message> <!-- Preloading Page--> <message name="IDS_SETTINGS_PRELOAD_PAGES_STANDARD_PRELOADING_WHEN_ON_BULLET_TWO" desc="Bullet point in the standard preloading and when on column. Informs the user about what the standard preloading setting does.">
diff --git a/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_google_chrome_strings.grdp b/chrome/app/settings_google_chrome_strings.grdp index c860b63e..c955c5b 100644 --- a/chrome/app/settings_google_chrome_strings.grdp +++ b/chrome/app/settings_google_chrome_strings.grdp
@@ -110,13 +110,9 @@ </if> <!-- Delete Browsing Data --> - <!-- TODO(crbug.com/397187800): Make DBDv2 strings translatable. --> - <message name="IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL" desc="Sub-label for the 'Manage other Data' row in the 'Delete Browsing Data' dialog, explaining to the user that passwords can only be deleted outside of Chrome." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL" desc="Sub-label for the 'Manage other Data' subpage entrypoint in the 'Delete Browsing Data' dialog, explaining to the user that passwords can only be deleted outside of Chrome."> Passwords can only be deleted outside Chrome </message> - <message name="IDS_SETTINGS_OTHER_DATA_DESCRIPTION" desc="Description text at the top of the 'Other data' subpage." translateable="false"> - This data is managed outside Chrome. To delete it, go to its management settings. - </message> <!-- Preloading Page--> <message name="IDS_SETTINGS_PRELOAD_PAGES_STANDARD_PRELOADING_WHEN_ON_BULLET_TWO" desc="Bullet point in the standard preloading and when on column. Informs the user about what the standard preloading setting does.">
diff --git a/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 new file mode 100644 index 0000000..025d0ab --- /dev/null +++ b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1
@@ -0,0 +1 @@ +3f2bf910ce5a9aa4a97622a5c521cdcb1de3afe5 \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 92c8251..7e023f6 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -798,6 +798,12 @@ <message name="IDS_SETTINGS_CLEAR_HOSTED_APP_DATA" desc="Checkbox for deleting data of hosted apps"> Hosted app data </message> + <message name="IDS_SETTINGS_CLEAR_PERIOD_15_MIN" desc="The option in the 'Delete browsing data' settings page time picker to delete browsing data from the last 15 minutes. The 'minutes' is shortened to 'min' to allow the time options in the time picker to fit in the screen."> + Last 15 min + </message> + <message name="IDS_SETTINGS_CLEAR_PERIOD_15_MINUTES" desc="The option to delete browsing data from the last 15 minutes."> + Last 15 minutes + </message> <message name="IDS_SETTINGS_CLEAR_PERIOD_HOUR" desc="The option to delete browsing data from the last hour."> Last hour </message> @@ -816,58 +822,54 @@ <message name="IDS_SETTINGS_NOTIFICATION_WARNING" desc="A warning that notifications will be disabled by deleting cookies for this site."> Notifications will be disabled </message> - <!-- TODO(crbug.com/397187800): Make DBDv2 strings translatable. --> - <message name="IDS_SETTINGS_CLEAR_BROWSING_DATA_SHOW_MORE" translateable="false"> + <message name="IDS_SETTINGS_CLEAR_BROWSING_DATA_SHOW_MORE" desc="Label of the 'Show more' button below the checkbox container in the 'Delete browsing data' dialog. Clicking on this button expands the checkbox container to show more checkbox data options."> Show more </message> - <message name="IDS_SETTINGS_CLEAR_BROWSING_DATA_MORE" translateable="false"> + <message name="IDS_SETTINGS_CLEAR_BROWSING_DATA_MORE" desc="Label of the 'More' chip in the time picker in the 'Delete browsing data' dialog. Clicking on this chip will show a menu with more time period options for deleting browsing data."> More </message> - <message name="IDS_SETTINGS_CLEAR_PERIOD_15_MIN" desc="The option in the 'Delete browsing data' settings page time picker to delete browsing data from the last 15 minutes. The 'minutes' is shortened to 'min' to allow the time options in the time picker to fit in the screen." translateable="false"> - Last 15 min - </message> - <message name="IDS_SETTINGS_CLEAR_PERIOD_15_MINUTES" desc="The option to delete browsing data from the last 15 minutes." translateable="false"> - Last 15 minutes - </message> - <message name="IDS_SETTINGS_MANAGE_IN_GOOGLE_PASSWORD_MANAGER" desc="Description for the 'Passwords and Passkeys' option in 'Other Google Data' page." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_IN_GOOGLE_PASSWORD_MANAGER" desc="Description for the 'Passwords and Passkeys' linkout in the 'Other Google Data' subpage inside the 'Delete browsing data' dialog. This lets users know that passwords and passkeys can be managed and deleted in Google password manager."> Manage in Google Password Manager </message> - <message name="IDS_SETTINGS_MANAGE_IN_YOUR_GOOGLE_ACCOUNT" desc="Description for a feature that can be managed in the user's Google account." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_IN_YOUR_GOOGLE_ACCOUNT" desc="Description for the MyActivity and Search History linkouts in the 'Other Google Data' subpage inside the 'Delete browsing data' dialog. This lets users know that this data can be managed and deleted in their Google account."> Manage in your Google Account </message> - <message name="IDS_SETTINGS_PASSWORDS_AND_PASSKEYS" desc="Label for the 'Passwords and Passkeys' option in 'Other Google Data' page." translateable="false"> + <message name="IDS_SETTINGS_PASSWORDS_AND_PASSKEYS" desc="Label for the 'Passwords and Passkeys' linkout in the 'Other Google Data' subpage inside the 'Delete browsing data' dialog, where the user can see and manage data that is stored outside of Chrome. This linkout is specifically for passwords and passkeys stored in Google password manager."> Passwords and passkeys </message> - <message name="IDS_SETTINGS_SEARCH_HISTORY" desc="Label for the 'Search history' option in 'Other Google Data' page." translateable="false"> + <message name="IDS_SETTINGS_SEARCH_HISTORY" desc="Label for the 'Search history' linkout in the 'Other Google Data' subpage inside the 'Delete browsing data' dialog, where the user can see and manage data that is stored outside of Chrome. This linkout is specifically for search history stored in the user's default search engine account."> Search history </message> - <message name="IDS_SETTINGS_OTHER_DATA_TITLE" desc="Title for the 'Other data' subpage that is linked from the clear Browse data dialog." translateable="false"> - Other data - </message> - <message name="IDS_SETTINGS_OTHER_GOOGLE_DATA_TITLE" desc="Title for the 'Other Google data' subpage that is linked from the clear Browse data dialog. This title is shown when Google is set as the default search engine on Chrome." translateable="false"> - Other Google data - </message> - <message name="IDS_SETTINGS_MY_ACTIVITY" desc="Label for the 'My Activity' option in 'Other Google Data' page." translateable="false"> + <message name="IDS_SETTINGS_MY_ACTIVITY" desc="Label for the 'My Activity' linkout in the 'Other Google Data' subpage inside the 'Delete browsing data' dialog, where the user can see and manage data that is stored outside of Chrome. This linkout is specifically for activity data stored in the user's Google account."> My Activity </message> - <message name="IDS_SETTINGS_DELETE_DATA_FROM_DEVICE" translateable="false"> + <message name="IDS_SETTINGS_OTHER_DATA_TITLE" desc="Title for the 'Other Data' subpage inside the 'Delete browsing data' dialog, where the user can see and manage data that is stored outside of Chrome. This is the title shown when the user did not set Google as their default search engine, indicating that they may have data stored outside of Google."> + Other data + </message> + <message name="IDS_SETTINGS_OTHER_GOOGLE_DATA_TITLE" desc="Title for the 'Other Google Data' subpage inside the 'Delete browsing data' dialog, where the user can see and manage data that is stored outside of Chrome. This is the title shown when the user set Google as their default search engine, indicating that all data linked in this subpage is stored within Google."> + Other Google data + </message> + <message name="IDS_SETTINGS_DELETE_DATA_FROM_DEVICE" desc="This is the label for the primary button on the 'Delete browsing data' dialog. Clicking on this will trigger the deletion. This is the label shown when account data cannot be cleared, for example: the user is signed out. It indicates that the deletion will only affect data stored on this device and will not affect synced data."> Delete from this device </message> - <message name="IDS_SETTINGS_DELETION_CONFIRMATION_TOAST_LABEL" translateable="false"> + <message name="IDS_SETTINGS_DELETION_CONFIRMATION_TOAST_LABEL" desc="This is the label for the confirmation toast shown on the 'Privacy and security' page after the deletion is completed in the 'Delete browsing data' dialog and the dialog was closed. It takes in another string for the the user-selected time period that the data was deleted within."> <ph name="TIME_PERIOD">$1<ex>Last 15 minutes</ex></ph> deleted </message> - <message name="IDS_SETTINGS_DELETION_CONFIRMATION_ALL_TIME_TOAST_LABEL" translateable="false"> + <message name="IDS_SETTINGS_DELETION_CONFIRMATION_ALL_TIME_TOAST_LABEL" desc="This is the label for the confirmation toast shown on the 'Privacy and security' page after the deletion is completed in the 'Delete browsing data' dialog and the dialog was closed. This is the label shown when the user selected the data to be deleted for all time."> Deleted </message> - <message name="IDS_SETTINGS_MANAGE_OTHER_GOOGLE_DATA_LABEL" desc="Label for the 'Manage other Google data' subpage entry-point in the 'Delete Browsing Data' dialog where the user can find link-outs to manage their data outside of Chrome. This is the label shown when the user has Google as their default search engine." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_OTHER_GOOGLE_DATA_LABEL" desc="Label for the 'Manage other Google data' subpage entry-point in the 'Delete Browsing Data' dialog where the user can find link-outs to manage their data outside of Chrome. This is the label shown when the user has Google as their default search engine."> Manage other Google data </message> - <message name="IDS_SETTINGS_MANAGE_OTHER_DATA_LABEL" desc="Label for the 'Manage other data' subpage entry-point in the 'Delete Browsing Data' dialog where the user can find link-outs to manage their data outside of Chrome. This is the label shown when the user does not have Google as their default search engine." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_OTHER_DATA_LABEL" desc="Label for the 'Manage other data' subpage entry-point in the 'Delete Browsing Data' dialog where the user can find link-outs to manage their data outside of Chrome. This is the label shown when the user does not have Google as their default search engine."> Manage other data </message> - <message name="IDS_SETTINGS_MANAGE_OTHER_DATA_SUB_LABEL" desc="Sub-label for the 'Manage other Google Data' option in the 'Delete Browsing Data' dialog, explaining to the user that search history and passwords can only be deleted outside of Chromium." translateable="false"> + <message name="IDS_SETTINGS_MANAGE_OTHER_DATA_SUB_LABEL" desc="Sub-label for the 'Manage other Google Data' option in the 'Delete Browsing Data' dialog, explaining to the user that search history and passwords can be deleted outside of Chrome in their respective management settings."> Search history and passwords can be deleted in their management settings </message> + <message name="IDS_SETTINGS_OTHER_DATA_DESCRIPTION" desc="Description text at the top of the 'Other Google data' subpage in the 'Delete browsing data' settings dialog. It informs users that data linked in this page are not managed or deleted in Chrome."> + To delete this data, go to its management settings + </message> <!-- Downloads Page --> <message name="IDS_SETTINGS_DOWNLOADS" desc="Name of the settings page which displays download preferences."> @@ -3172,6 +3174,12 @@ <message name="IDS_SETTINGS_SITE_SETTINGS_RESET_MENU" desc="Label for the menu item to remove the permission for a particular site (make it ask you again next time)."> Remove </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_RESET_FROM_LIST_A11Y" desc="Text read by screen readers when focusing on the remove icon for a particular site. Activating this button will remove the permission for the selected site. This text only announced by screen readers and is not visible in the UI."> + Remove <ph name="SITE">$1<ex>www.example.com</ex></ph> from the <ph name="SECTION_HEADER">$2<ex>Allowed to see your location</ex></ph> list + </message> + <message name="IDS_SETTINGS_SITE_SETTINGS_VIEW_FROM_LIST_A11Y" desc="Text read by screen readers when focusing on the view icon for a particular site. Activating this button will open the subpage for the permission for the selected site. This text only announced by screen readers and is not visible in the UI."> + View site details for <ph name="SITE">$1<ex>www.example.com</ex></ph> from the <ph name="SECTION_HEADER">$2<ex>Allowed to see your location</ex></ph> list + </message> <message name="IDS_SETTINGS_SITE_SETTINGS_SESSION_ONLY_MENU" desc="Label for the menu item to set cookies to be deleted on browser exit."> Delete on exit </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_MORE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_MORE.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_MORE.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_SHOW_MORE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_SHOW_MORE.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_BROWSING_DATA_SHOW_MORE.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MIN.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MIN.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MIN.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MINUTES.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MINUTES.png.sha1 new file mode 100644 index 0000000..b56f96f --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CLEAR_PERIOD_15_MINUTES.png.sha1
@@ -0,0 +1 @@ +730953dc23f4645f8a15d20cb0f7efc2ab460bd6 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETE_DATA_FROM_DEVICE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETE_DATA_FROM_DEVICE.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETE_DATA_FROM_DEVICE.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_ALL_TIME_TOAST_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_ALL_TIME_TOAST_LABEL.png.sha1 new file mode 100644 index 0000000..858d91c --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_ALL_TIME_TOAST_LABEL.png.sha1
@@ -0,0 +1 @@ +f85d237b0d9862b2a013633bb6050eef3f65cd88 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_TOAST_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_TOAST_LABEL.png.sha1 new file mode 100644 index 0000000..b56f96f --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_DELETION_CONFIRMATION_TOAST_LABEL.png.sha1
@@ -0,0 +1 @@ +730953dc23f4645f8a15d20cb0f7efc2ab460bd6 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_GOOGLE_PASSWORD_MANAGER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_GOOGLE_PASSWORD_MANAGER.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_GOOGLE_PASSWORD_MANAGER.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_YOUR_GOOGLE_ACCOUNT.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_YOUR_GOOGLE_ACCOUNT.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_IN_YOUR_GOOGLE_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_LABEL.png.sha1 new file mode 100644 index 0000000..3f1b617 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_LABEL.png.sha1
@@ -0,0 +1 @@ +18e627ab9a77a5eeec742aeb53cabb2ecf2cd2a9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_SUB_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_SUB_LABEL.png.sha1 new file mode 100644 index 0000000..3f1b617 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_DATA_SUB_LABEL.png.sha1
@@ -0,0 +1 @@ +18e627ab9a77a5eeec742aeb53cabb2ecf2cd2a9 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_GOOGLE_DATA_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_GOOGLE_DATA_LABEL.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_OTHER_GOOGLE_DATA_LABEL.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1 new file mode 100644 index 0000000..34bd5f79 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MANAGE_PASSWORDS_SUB_LABEL.png.sha1
@@ -0,0 +1 @@ +c4b87f9fb3fbf45c8d71039cf07b43b8507f7e5d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_MY_ACTIVITY.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MY_ACTIVITY.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_MY_ACTIVITY.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_DESCRIPTION.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_TITLE.png.sha1 new file mode 100644 index 0000000..bc8417c --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_DATA_TITLE.png.sha1
@@ -0,0 +1 @@ +78d2d5ff8fbde5a43a5c76362c6641bc4d130fff \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_GOOGLE_DATA_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_GOOGLE_DATA_TITLE.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_OTHER_GOOGLE_DATA_TITLE.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_AND_PASSKEYS.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_AND_PASSKEYS.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_AND_PASSKEYS.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_HISTORY.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_HISTORY.png.sha1 new file mode 100644 index 0000000..c63cdc3 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SEARCH_HISTORY.png.sha1
@@ -0,0 +1 @@ +4d2a10604c126fb82601ebddd5bd02e2e926eddb \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_RESET_FROM_LIST_A11Y.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_RESET_FROM_LIST_A11Y.png.sha1 new file mode 100644 index 0000000..7116582 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_RESET_FROM_LIST_A11Y.png.sha1
@@ -0,0 +1 @@ +0d23bf90258a1dc02ac1acc16c803d0735e8105d \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_VIEW_FROM_LIST_A11Y.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_VIEW_FROM_LIST_A11Y.png.sha1 new file mode 100644 index 0000000..830bbed8 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_SITE_SETTINGS_VIEW_FROM_LIST_A11Y.png.sha1
@@ -0,0 +1 @@ +202e40f6fa4227279202e32f654819b438779617 \ No newline at end of file
diff --git a/chrome/app/shared_settings_strings.grdp b/chrome/app/shared_settings_strings.grdp index 4b19823..921094e 100644 --- a/chrome/app/shared_settings_strings.grdp +++ b/chrome/app/shared_settings_strings.grdp
@@ -251,12 +251,6 @@ </message> </else> </if> - <message name="IDS_SETTINGS_LINKDOCTOR_PREF" desc="The documentation string of the 'Use Link Doctor' preference to help with navigation errors."> - Show suggestions for similar pages when a page can't be found - </message> - <message name="IDS_SETTINGS_LINKDOCTOR_PREF_DESC" desc="The description of the 'Use Link Doctor' preference to help with navigation errors."> - Sends the web address of the page you're trying to reach to Google - </message> <message name="IDS_SETTINGS_SUGGEST_PREF" desc="The label of the checkbox to enable/disable sending omnibox input to the user's default search engine to get additional suggestions."> Improve search suggestions </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 028209ef..7b22c75b 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -601,6 +601,7 @@ {"contextual_only", "true"}}; const FeatureEntry::FeatureParam kCCTAdaptiveButtonOpenInBrowserCPA[] = { {"open_in_browser", "true"}, + {"default_variant", "15"}, // 15 == Open In Browser {"contextual_only", "true"}}; const FeatureEntry::FeatureParam kCCTAdaptiveButtonMenuOpenInBrowserTop[] = { {"open_in_browser", "true"}, @@ -2550,10 +2551,6 @@ }; const FeatureEntry::FeatureParam - kResamplingScrollEventsPredictionTimeBasedEnabled[] = { - {"mode", features::kPredictionTypeTimeBased}, - {"latency", features::kPredictionTypeDefaultTime}}; -const FeatureEntry::FeatureParam kResamplingScrollEventsPredictionFramesBasedEnabledV1[] = { {"mode", features::kPredictionTypeFramesBased}, {"latency", features::kPredictionTypeDefaultFramesVariation1}}; @@ -2567,9 +2564,6 @@ {"latency", features::kPredictionTypeDefaultFramesVariation3}}; const FeatureEntry::FeatureVariation kResamplingScrollEventsExperimentalPredictionVariations[] = { - {features::kPredictionTypeTimeBased, - kResamplingScrollEventsPredictionTimeBasedEnabled, - std::size(kResamplingScrollEventsPredictionTimeBasedEnabled), nullptr}, {"frames 0.25", kResamplingScrollEventsPredictionFramesBasedEnabledV1, std::size(kResamplingScrollEventsPredictionFramesBasedEnabledV1), nullptr}, @@ -7000,6 +6994,12 @@ FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kOmniboxMobileParityUpdate, kOmniboxMobileParityVariants, "OmniboxMobileParityUpdate")}, + + {"omnibox-mobile-parity-update-v2", + flag_descriptions::kOmniboxMobileParityUpdateV2Name, + flag_descriptions::kOmniboxMobileParityUpdateV2Description, kOsAndroid, + FEATURE_VALUE_TYPE(omnibox::kOmniboxMobileParityUpdateV2)}, + #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_WIN) {"omnibox-on-device-head-suggestions",
diff --git a/chrome/browser/actor/actor_test_util.cc b/chrome/browser/actor/actor_test_util.cc index 868603f..f8b7dc8 100644 --- a/chrome/browser/actor/actor_test_util.cc +++ b/chrome/browser/actor/actor_test_util.cc
@@ -44,20 +44,6 @@ return action; } -BrowserAction MakeClick(RenderFrameHost& rfh, const gfx::Point& click_point) { - BrowserAction action; - ClickAction* click = action.add_actions()->mutable_click(); - Coordinate* coordinate = click->mutable_target()->mutable_coordinate(); - coordinate->set_x(click_point.x()); - coordinate->set_y(click_point.y()); - click->mutable_target()->mutable_document_identifier()->set_serialized_token( - *DocumentIdentifierUserData::GetDocumentIdentifier( - rfh.GetGlobalFrameToken())); - click->set_click_type(ClickAction::LEFT); - click->set_click_count(ClickAction::SINGLE); - return action; -} - BrowserAction MakeClick(const gfx::Point& click_point) { BrowserAction action; ClickAction* click = action.add_actions()->mutable_click(); @@ -91,16 +77,12 @@ return action; } -BrowserAction MakeMouseMove(RenderFrameHost& rfh, - const gfx::Point& move_point) { +BrowserAction MakeMouseMove(const gfx::Point& move_point) { BrowserAction action; MoveMouseAction* move = action.add_actions()->mutable_move_mouse(); Coordinate* coordinate = move->mutable_target()->mutable_coordinate(); coordinate->set_x(move_point.x()); coordinate->set_y(move_point.y()); - move->mutable_target()->mutable_document_identifier()->set_serialized_token( - *DocumentIdentifierUserData::GetDocumentIdentifier( - rfh.GetGlobalFrameToken())); return action; } @@ -130,8 +112,7 @@ return action; } -BrowserAction MakeType(RenderFrameHost& rfh, - const gfx::Point& type_point, +BrowserAction MakeType(const gfx::Point& type_point, std::string_view text, bool follow_by_enter) { BrowserAction action; @@ -139,10 +120,6 @@ Coordinate* coordinate = type_action->mutable_target()->mutable_coordinate(); coordinate->set_x(type_point.x()); coordinate->set_y(type_point.y()); - type_action->mutable_target() - ->mutable_document_identifier() - ->set_serialized_token(*DocumentIdentifierUserData::GetDocumentIdentifier( - rfh.GetGlobalFrameToken())); type_action->set_text(text); // TODO(crbug.com/409570203): Tests should set a mode. type_action->set_mode( @@ -203,8 +180,7 @@ return action; } -BrowserAction MakeDragAndRelease(RenderFrameHost& rfh, - const gfx::Point& from_point, +BrowserAction MakeDragAndRelease(const gfx::Point& from_point, const gfx::Point& to_point) { BrowserAction action; DragAndReleaseAction* drag_and_release = @@ -213,18 +189,10 @@ from_point.x()); drag_and_release->mutable_from_target()->mutable_coordinate()->set_y( from_point.y()); - drag_and_release->mutable_from_target() - ->mutable_document_identifier() - ->set_serialized_token(*DocumentIdentifierUserData::GetDocumentIdentifier( - rfh.GetGlobalFrameToken())); drag_and_release->mutable_to_target()->mutable_coordinate()->set_x( to_point.x()); drag_and_release->mutable_to_target()->mutable_coordinate()->set_y( to_point.y()); - drag_and_release->mutable_to_target() - ->mutable_document_identifier() - ->set_serialized_token(*DocumentIdentifierUserData::GetDocumentIdentifier( - rfh.GetGlobalFrameToken())); return action; }
diff --git a/chrome/browser/actor/actor_test_util.h b/chrome/browser/actor/actor_test_util.h index 916c368..9a3297dc 100644 --- a/chrome/browser/actor/actor_test_util.h +++ b/chrome/browser/actor/actor_test_util.h
@@ -23,16 +23,12 @@ int content_node_id); optimization_guide::proto::BrowserAction MakeClick( const gfx::Point& click_point); -optimization_guide::proto::BrowserAction MakeClick( - content::RenderFrameHost& rfh, - const gfx::Point& click_point); optimization_guide::proto::BrowserAction MakeHistoryBack(); optimization_guide::proto::BrowserAction MakeHistoryForward(); optimization_guide::proto::BrowserAction MakeMouseMove( content::RenderFrameHost& rfh, int content_node_id); optimization_guide::proto::BrowserAction MakeMouseMove( - content::RenderFrameHost& rfh, const gfx::Point& move_point); optimization_guide::proto::BrowserAction MakeNavigate( std::string_view target_url); @@ -40,8 +36,7 @@ int content_node_id, std::string_view text, bool follow_by_enter); -optimization_guide::proto::BrowserAction MakeType(content::RenderFrameHost& rfh, - const gfx::Point& type_point, +optimization_guide::proto::BrowserAction MakeType(const gfx::Point& type_point, std::string_view text, bool follow_by_enter); optimization_guide::proto::BrowserAction MakeSelect( @@ -55,7 +50,6 @@ float scroll_offset_x, float scroll_offset_y); optimization_guide::proto::BrowserAction MakeDragAndRelease( - content::RenderFrameHost& rfh, const gfx::Point& from_point, const gfx::Point& to_point); optimization_guide::proto::BrowserAction MakeWait();
diff --git a/chrome/browser/actor/browser_action_util.cc b/chrome/browser/actor/browser_action_util.cc index 01430dc4..982bd34 100644 --- a/chrome/browser/actor/browser_action_util.cc +++ b/chrome/browser/actor/browser_action_util.cc
@@ -6,6 +6,7 @@ #include <optional> +#include "base/notimplemented.h" #include "chrome/browser/actor/tools/click_tool_request.h" #include "chrome/browser/actor/tools/drag_and_release_tool_request.h" #include "chrome/browser/actor/tools/history_tool_request.h" @@ -17,6 +18,7 @@ #include "chrome/browser/actor/tools/tool_request.h" #include "chrome/browser/actor/tools/type_tool_request.h" #include "chrome/browser/actor/tools/wait_tool_request.h" +#include "chrome/common/actor/actor_constants.h" #include "chrome/common/actor/actor_logging.h" #include "components/optimization_guide/content/browser/page_content_proto_provider.h" #include "components/optimization_guide/proto/features/actions_data.pb.h" @@ -66,52 +68,20 @@ return tab_handle; } -template <class T> -PageScopedParams GetPageScopedParams(const T& action, - TabInterface* deprecated_fallback_tab) { - std::string document_identifier; - if (action.has_target()) { - document_identifier = - action.target().document_identifier().serialized_token(); - } - - tabs::TabHandle tab_handle; - if (action.has_tab_id()) { - tab_handle = TabHandle(action.tab_id()); - } else if (deprecated_fallback_tab) { - tab_handle = deprecated_fallback_tab->GetHandle(); - } - return {document_identifier, tab_handle}; -} - -// DragAndRelease is unusual in that it has no target, it has a from_target and -// to_target. Specialize and use the from_target as the document-scoping target. -template <> -PageScopedParams GetPageScopedParams<DragAndReleaseAction>( - const DragAndReleaseAction& action, - TabInterface* deprecated_fallback_tab) { - std::string document_identifier; - if (action.has_from_target()) { - document_identifier = - action.from_target().document_identifier().serialized_token(); - } - - tabs::TabHandle tab_handle; - if (action.has_tab_id()) { - tab_handle = TabHandle(action.tab_id()); - } else if (deprecated_fallback_tab) { - tab_handle = deprecated_fallback_tab->GetHandle(); - } - return {document_identifier, tab_handle}; -} - -PageToolRequest::Target ToPageToolTarget( +std::optional<PageToolRequest::Target> ToPageToolTarget( const optimization_guide::proto::ActionTarget& target) { + // A valid target must have either a coordinate or a + // document_identifier-dom_node_id pair. if (target.has_coordinate()) { return PageToolRequest::Target( gfx::Point(target.coordinate().x(), target.coordinate().y())); } else { - return PageToolRequest::Target(target.content_node_id()); + if (!target.has_content_node_id() || !target.has_document_identifier()) { + return std::nullopt; + } + return PageToolRequest::Target( + {target.content_node_id(), + target.document_identifier().serialized_token()}); } } std::unique_ptr<ToolRequest> CreateClickRequest( @@ -120,10 +90,10 @@ using ClickCount = ClickToolRequest::ClickCount; using ClickType = ClickToolRequest::ClickType; - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); if (!action.has_target() || !action.has_click_count() || - !action.has_click_type() || page.tab_handle == TabHandle::Null()) { + !action.has_click_type() || tab_handle == TabHandle::Null()) { return nullptr; } @@ -163,9 +133,13 @@ break; } - return std::make_unique<ClickToolRequest>( - page.tab_handle, page.document_identifier, - ToPageToolTarget(action.target()), type, count); + auto target = ToPageToolTarget(action.target()); + if (!target.has_value()) { + return nullptr; + } + + return std::make_unique<ClickToolRequest>(tab_handle, target.value(), type, + count); } std::unique_ptr<ToolRequest> CreateTypeRequest( @@ -173,10 +147,10 @@ TabInterface* deprecated_fallback_tab) { using TypeMode = TypeToolRequest::Mode; - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); if (!action.has_target() || !action.has_text() || !action.has_mode() || - !action.has_follow_by_enter() || page.tab_handle == TabHandle::Null()) { + !action.has_follow_by_enter() || tab_handle == TabHandle::Null()) { return nullptr; } @@ -200,10 +174,14 @@ mode = TypeMode::kReplace; break; } - return std::make_unique<TypeToolRequest>( - page.tab_handle, page.document_identifier, - ToPageToolTarget(action.target()), action.text(), - action.follow_by_enter(), mode); + + auto target = ToPageToolTarget(action.target()); + if (!target.has_value()) { + return nullptr; + } + return std::make_unique<TypeToolRequest>(tab_handle, target.value(), + action.text(), + action.follow_by_enter(), mode); } std::unique_ptr<ToolRequest> CreateScrollRequest( @@ -211,32 +189,33 @@ TabInterface* deprecated_fallback_tab) { using Direction = ScrollToolRequest::Direction; - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); if (!action.has_direction() || !action.has_distance() || - page.tab_handle == TabHandle::Null()) { + tab_handle == TabHandle::Null()) { return nullptr; } - PageToolRequest::Target page_target; - + std::optional<PageToolRequest::Target> target; if (action.has_target()) { - page_target = ToPageToolTarget(action.target()); + target = ToPageToolTarget(action.target()); } else { // Scroll action may omit a target which means "target the viewport". - // TODO(bokan): This can be removed once the scroll action provides the main - // document's id in these cases. - page_target = std::nullopt; - if (page.document_identifier.empty()) { - TabInterface* tab = page.tab_handle.Get(); - if (!tab) { - return nullptr; - } - page.document_identifier = - DocumentIdentifierUserData::GetOrCreateForCurrentDocument( - tab->GetContents()->GetPrimaryMainFrame()) - ->serialized_token(); + TabInterface* tab = tab_handle.Get(); + if (!tab) { + return nullptr; } + std::string document_identifier = + DocumentIdentifierUserData::GetOrCreateForCurrentDocument( + tab->GetContents()->GetPrimaryMainFrame()) + ->serialized_token(); + + target.emplace(PageToolRequest::Target( + {/*dom_node_id=*/kRootElementDomNodeId, document_identifier})); + } + + if (!target) { + return nullptr; } Direction direction; @@ -263,52 +242,66 @@ break; } - return std::make_unique<ScrollToolRequest>( - page.tab_handle, page.document_identifier, page_target, direction, - action.distance()); + return std::make_unique<ScrollToolRequest>(tab_handle, target.value(), + direction, action.distance()); } std::unique_ptr<ToolRequest> CreateMoveMouseRequest( const MoveMouseAction& action, TabInterface* deprecated_fallback_tab) { - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); - if (!action.has_target() || page.tab_handle == TabHandle::Null()) { + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); + if (!action.has_target() || tab_handle == TabHandle::Null()) { return nullptr; } - return std::make_unique<MoveMouseToolRequest>( - page.tab_handle, page.document_identifier, - ToPageToolTarget(action.target())); + auto target = ToPageToolTarget(action.target()); + if (!target.has_value()) { + return nullptr; + } + + return std::make_unique<MoveMouseToolRequest>(tab_handle, target.value()); } std::unique_ptr<ToolRequest> CreateDragAndReleaseRequest( const DragAndReleaseAction& action, TabInterface* deprecated_fallback_tab) { - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); if (!action.has_from_target() || !action.has_to_target() || - page.tab_handle == TabHandle::Null()) { + tab_handle == TabHandle::Null()) { + return nullptr; + } + + auto from_target = ToPageToolTarget(action.from_target()); + if (!from_target.has_value()) { + return nullptr; + } + + auto to_target = ToPageToolTarget(action.to_target()); + if (!to_target.has_value()) { return nullptr; } return std::make_unique<DragAndReleaseToolRequest>( - page.tab_handle, page.document_identifier, - ToPageToolTarget(action.from_target()), - ToPageToolTarget(action.to_target())); + tab_handle, from_target.value(), to_target.value()); } std::unique_ptr<ToolRequest> CreateSelectRequest( const SelectAction& action, TabInterface* deprecated_fallback_tab) { - PageScopedParams page = GetPageScopedParams(action, deprecated_fallback_tab); + TabHandle tab_handle = GetTabHandle(action, deprecated_fallback_tab); if (!action.has_value() || !action.has_target() || - page.tab_handle == TabHandle::Null()) { + tab_handle == TabHandle::Null()) { return nullptr; } - return std::make_unique<SelectToolRequest>( - page.tab_handle, page.document_identifier, - ToPageToolTarget(action.target()), action.value()); + auto target = ToPageToolTarget(action.target()); + if (!target.has_value()) { + return nullptr; + } + + return std::make_unique<SelectToolRequest>(tab_handle, target.value(), + action.value()); } std::unique_ptr<ToolRequest> CreateNavigateRequest(
diff --git a/chrome/browser/actor/tools/click_tool_request.cc b/chrome/browser/actor/tools/click_tool_request.cc index 15a6bcd..6704466 100644 --- a/chrome/browser/actor/tools/click_tool_request.cc +++ b/chrome/browser/actor/tools/click_tool_request.cc
@@ -11,11 +11,10 @@ using ::tabs::TabHandle; ClickToolRequest::ClickToolRequest(TabHandle tab_handle, - std::string_view document_identifier, const Target& target, ClickType type, ClickCount count) - : PageToolRequest(tab_handle, document_identifier, target), + : PageToolRequest(tab_handle, target), click_type_(type), click_count_(count) {}
diff --git a/chrome/browser/actor/tools/click_tool_request.h b/chrome/browser/actor/tools/click_tool_request.h index cff83f3..6bdb521b 100644 --- a/chrome/browser/actor/tools/click_tool_request.h +++ b/chrome/browser/actor/tools/click_tool_request.h
@@ -19,7 +19,6 @@ enum class ClickCount { kSingle, kDouble }; ClickToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, const Target& target, ClickType type, ClickCount count);
diff --git a/chrome/browser/actor/tools/drag_and_release_tool_request.cc b/chrome/browser/actor/tools/drag_and_release_tool_request.cc index 4ce8671..a02971a 100644 --- a/chrome/browser/actor/tools/drag_and_release_tool_request.cc +++ b/chrome/browser/actor/tools/drag_and_release_tool_request.cc
@@ -10,12 +10,10 @@ using ::tabs::TabHandle; -DragAndReleaseToolRequest::DragAndReleaseToolRequest( - TabHandle tab_handle, - std::string_view document_identifier, - const Target& from_target, - const Target& to_target) - : PageToolRequest(tab_handle, document_identifier, from_target), +DragAndReleaseToolRequest::DragAndReleaseToolRequest(TabHandle tab_handle, + const Target& from_target, + const Target& to_target) + : PageToolRequest(tab_handle, from_target), from_target_(from_target), to_target_(to_target) {}
diff --git a/chrome/browser/actor/tools/drag_and_release_tool_request.h b/chrome/browser/actor/tools/drag_and_release_tool_request.h index 31d331c..e260c24 100644 --- a/chrome/browser/actor/tools/drag_and_release_tool_request.h +++ b/chrome/browser/actor/tools/drag_and_release_tool_request.h
@@ -19,7 +19,6 @@ class DragAndReleaseToolRequest : public PageToolRequest { public: DragAndReleaseToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, const Target& from_target, const Target& to_target); ~DragAndReleaseToolRequest() override;
diff --git a/chrome/browser/actor/tools/history_tool.cc b/chrome/browser/actor/tools/history_tool.cc index e5098739..8df47bd 100644 --- a/chrome/browser/actor/tools/history_tool.cc +++ b/chrome/browser/actor/tools/history_tool.cc
@@ -33,9 +33,13 @@ using ::tabs::TabHandle; using ::tabs::TabInterface; -HistoryTool::HistoryTool(WebContents& web_contents, +HistoryTool::HistoryTool(TaskId task_id, + AggregatedJournal& journal, + WebContents& web_contents, HistoryToolRequest::Direction direction) - : WebContentsObserver(&web_contents), direction_(direction) {} + : Tool(task_id, journal), + WebContentsObserver(&web_contents), + direction_(direction) {} HistoryTool::~HistoryTool() = default;
diff --git a/chrome/browser/actor/tools/history_tool.h b/chrome/browser/actor/tools/history_tool.h index 6262ee5..17adabc 100644 --- a/chrome/browser/actor/tools/history_tool.h +++ b/chrome/browser/actor/tools/history_tool.h
@@ -29,7 +29,9 @@ // Performs a history navigation in a WebContents. class HistoryTool : public Tool, content::WebContentsObserver { public: - HistoryTool(content::WebContents& web_contents, + HistoryTool(TaskId task_id, + AggregatedJournal& journal, + content::WebContents& web_contents, HistoryToolRequest::Direction direction); ~HistoryTool() override;
diff --git a/chrome/browser/actor/tools/history_tool_request.cc b/chrome/browser/actor/tools/history_tool_request.cc index ded0730..45d58555 100644 --- a/chrome/browser/actor/tools/history_tool_request.cc +++ b/chrome/browser/actor/tools/history_tool_request.cc
@@ -18,6 +18,7 @@ HistoryToolRequest::~HistoryToolRequest() = default; ToolRequest::CreateToolResult HistoryToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { TabInterface* tab = GetTabHandle().Get(); @@ -27,7 +28,8 @@ } CHECK(tab->GetContents()); - return {std::make_unique<HistoryTool>(*tab->GetContents(), direction_), + return {std::make_unique<HistoryTool>(task_id, journal, *tab->GetContents(), + direction_), MakeOkResult()}; }
diff --git a/chrome/browser/actor/tools/history_tool_request.h b/chrome/browser/actor/tools/history_tool_request.h index 16f9c17..edad6d8 100644 --- a/chrome/browser/actor/tools/history_tool_request.h +++ b/chrome/browser/actor/tools/history_tool_request.h
@@ -26,7 +26,8 @@ ~HistoryToolRequest() override; // ToolRequest - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; // Whether the navigation is backwards or forwards in session history.
diff --git a/chrome/browser/actor/tools/move_mouse_tool_request.cc b/chrome/browser/actor/tools/move_mouse_tool_request.cc index 41a1a3a..d8b6fa5 100644 --- a/chrome/browser/actor/tools/move_mouse_tool_request.cc +++ b/chrome/browser/actor/tools/move_mouse_tool_request.cc
@@ -11,9 +11,8 @@ using ::tabs::TabHandle; MoveMouseToolRequest::MoveMouseToolRequest(TabHandle tab_handle, - std::string_view document_identifier, const Target& target) - : PageToolRequest(tab_handle, document_identifier, target) {} + : PageToolRequest(tab_handle, target) {} MoveMouseToolRequest::~MoveMouseToolRequest() = default;
diff --git a/chrome/browser/actor/tools/move_mouse_tool_request.h b/chrome/browser/actor/tools/move_mouse_tool_request.h index fbd1a2d..2ad7943 100644 --- a/chrome/browser/actor/tools/move_mouse_tool_request.h +++ b/chrome/browser/actor/tools/move_mouse_tool_request.h
@@ -16,9 +16,7 @@ // Injects a mouse move event at the given target. class MoveMouseToolRequest : public PageToolRequest { public: - MoveMouseToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, - const Target& target); + MoveMouseToolRequest(tabs::TabHandle tab_handle, const Target& target); ~MoveMouseToolRequest() override; // ToolRequest
diff --git a/chrome/browser/actor/tools/navigate_tool.cc b/chrome/browser/actor/tools/navigate_tool.cc index 07edfea..38d6f5bd 100644 --- a/chrome/browser/actor/tools/navigate_tool.cc +++ b/chrome/browser/actor/tools/navigate_tool.cc
@@ -20,8 +20,11 @@ namespace actor { -NavigateTool::NavigateTool(WebContents& web_contents, const GURL& url) - : WebContentsObserver(&web_contents), url_(url) {} +NavigateTool::NavigateTool(TaskId task_id, + AggregatedJournal& journal, + WebContents& web_contents, + const GURL& url) + : Tool(task_id, journal), WebContentsObserver(&web_contents), url_(url) {} NavigateTool::~NavigateTool() = default;
diff --git a/chrome/browser/actor/tools/navigate_tool.h b/chrome/browser/actor/tools/navigate_tool.h index 8a5f771..418e3032 100644 --- a/chrome/browser/actor/tools/navigate_tool.h +++ b/chrome/browser/actor/tools/navigate_tool.h
@@ -22,7 +22,10 @@ // Navigates a the primary main frame in a WebContents to the given URL. class NavigateTool : public Tool, content::WebContentsObserver { public: - NavigateTool(content::WebContents& web_contents, const GURL& url); + NavigateTool(TaskId task_id, + AggregatedJournal& journal, + content::WebContents& web_contents, + const GURL& url); ~NavigateTool() override; // actor::Tool
diff --git a/chrome/browser/actor/tools/navigate_tool_request.cc b/chrome/browser/actor/tools/navigate_tool_request.cc index 518db2b..297b4e8 100644 --- a/chrome/browser/actor/tools/navigate_tool_request.cc +++ b/chrome/browser/actor/tools/navigate_tool_request.cc
@@ -19,6 +19,7 @@ NavigateToolRequest::~NavigateToolRequest() = default; ToolRequest::CreateToolResult NavigateToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { TabInterface* tab = GetTabHandle().Get(); if (!tab) { @@ -26,7 +27,8 @@ "The tab is no longer present.")}; } - return {std::make_unique<NavigateTool>(*tab->GetContents(), url_), + return {std::make_unique<NavigateTool>(task_id, journal, *tab->GetContents(), + url_), MakeOkResult()}; }
diff --git a/chrome/browser/actor/tools/navigate_tool_request.h b/chrome/browser/actor/tools/navigate_tool_request.h index 642c737..b9242df 100644 --- a/chrome/browser/actor/tools/navigate_tool_request.h +++ b/chrome/browser/actor/tools/navigate_tool_request.h
@@ -21,7 +21,8 @@ ~NavigateToolRequest() override; // ToolRequest - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; private:
diff --git a/chrome/browser/actor/tools/page_tool.cc b/chrome/browser/actor/tools/page_tool.cc index bf703e56..4ecc8245 100644 --- a/chrome/browser/actor/tools/page_tool.cc +++ b/chrome/browser/actor/tools/page_tool.cc
@@ -35,8 +35,7 @@ using ::content::WebContents; using ::content::WebContentsObserver; using ::optimization_guide::DocumentIdentifierUserData; -using optimization_guide::proto::ActionTarget; -using optimization_guide::proto::AnnotatedPageContent; +using ::optimization_guide::proto::AnnotatedPageContent; using ::tabs::TabHandle; using ::tabs::TabInterface; @@ -98,10 +97,8 @@ return root_frame; } -RenderFrameHost* FindTargetLocalRootFrame( - TabHandle tab_handle, - std::optional<std::string> document_identifier, - PageToolRequest::Target target) { +RenderFrameHost* FindTargetLocalRootFrame(TabHandle tab_handle, + PageToolRequest::Target target) { TabInterface* tab = tab_handle.Get(); if (!tab) { return nullptr; @@ -109,24 +106,19 @@ WebContents& contents = *tab->GetContents(); - if (std::holds_alternative<PageToolRequest::CoordinateTarget>(target)) { - auto coordinate = std::get<PageToolRequest::CoordinateTarget>(target); - + if (target.is_coordinate()) { RenderWidgetHost* target_rwh = - contents.FindWidgetAtPoint(gfx::PointF(coordinate)); + contents.FindWidgetAtPoint(gfx::PointF(target.coordinate())); if (!target_rwh) { return nullptr; } return GetRootFrameForWidget(contents, target_rwh); } - CHECK(std::holds_alternative<PageToolRequest::NodeTarget>(target)); - - CHECK(document_identifier.has_value()); - const std::string& serialized_token = document_identifier.value(); + CHECK(target.is_node()); RenderFrameHost* target_frame = GetRenderFrameForDocumentIdentifier( - *tab->GetContents(), serialized_token); + *tab->GetContents(), target.node().document_identifier); // After finding the target frame, walk up to its local root. return GetLocalRoot(target_frame); @@ -141,7 +133,7 @@ WebContents& web_contents, const AnnotatedPageContent* last_observed_page_content) { // Frame validation is performed only when targeting using coordinates. - CHECK(std::holds_alternative<PageToolRequest::CoordinateTarget>(target)); + CHECK(target.is_coordinate()); if (!last_observed_page_content) { // TODO(bokan): We can't perform a TOCTOU check If there's no last @@ -150,7 +142,7 @@ } // TODO(bokan): This helper should take a gfx::Point. - auto coordinate = std::get<PageToolRequest::CoordinateTarget>(target); + gfx::Point coordinate = target.coordinate(); optimization_guide::proto::Coordinate apc_coordinate; apc_coordinate.set_x(coordinate.x()); apc_coordinate.set_y(coordinate.y()); @@ -205,18 +197,10 @@ base::OnceClosure callback_; }; -PageTool::PageTool(const PageToolRequest& request, AggregatedJournal& journal) - : request_(request.Clone()) { - // TODO(crbug.com/411462297): We shouldn't assume we have a frame until TOCTOU - // checks are done - a frame should only be resolved at that time. Same for - // tab. - RenderFrameHost* frame = FindTargetLocalRootFrame( - request.GetTabHandle(), request.DocumentIdentifier(), - request.GetTarget()); - if (frame) { - journal.EnsureJournalBound(*frame); - } -} +PageTool::PageTool(TaskId task_id, + AggregatedJournal& journal, + const PageToolRequest& request) + : Tool(task_id, journal), request_(request.Clone()) {} PageTool::~PageTool() = default; @@ -227,21 +211,20 @@ } mojom::ActionResultPtr PageTool::TimeOfUseValidation( - const AnnotatedPageContent* last_observation) const { - RenderFrameHost* frame = FindTargetLocalRootFrame( - request_->GetTabHandle(), request_->DocumentIdentifier(), - request_->GetTarget()); + const AnnotatedPageContent* last_observation) { + TabInterface* tab = request_->GetTabHandle().Get(); + if (!tab) { + return MakeResult(mojom::ActionResultCode::kTabWentAway); + } + + RenderFrameHost* frame = + FindTargetLocalRootFrame(request_->GetTabHandle(), request_->GetTarget()); if (!frame) { return MakeResult(mojom::ActionResultCode::kFrameWentAway); } - TabInterface* tab = request_->GetTabHandle().Get(); - // If the frame still exists the tab must as well. - CHECK(tab); - // Perform validation for coordinate based target only. - if (std::holds_alternative<PageToolRequest::CoordinateTarget>( - request_->GetTarget())) { + if (request_->GetTarget().is_coordinate()) { if (!ValidateTargetFrameCandidate(request_->GetTarget(), frame, *tab->GetContents(), last_observation)) { return MakeResult( @@ -249,17 +232,20 @@ } } + has_completed_time_of_use_ = true; + target_document_ = frame->GetWeakDocumentPtr(); + return MakeOkResult(); } void PageTool::Invoke(InvokeCallback callback) { - invoke_callback_ = std::move(callback); - // Frame was validated in TimeOfUseValidation. - RenderFrameHost* frame = FindTargetLocalRootFrame( - request_->GetTabHandle(), request_->DocumentIdentifier(), - request_->GetTarget()); - CHECK(frame); + CHECK(GetFrame()); + RenderFrameHost& frame = *GetFrame(); + + journal().EnsureJournalBound(frame); + + invoke_callback_ = std::move(callback); auto request = actor::mojom::ToolInvocation::New(); request->action = request_->ToMojoToolAction(); @@ -267,7 +253,7 @@ // ToolRequest params are checked for validity at creation. CHECK(request->action); - frame->GetRemoteAssociatedInterfaces()->GetInterface(&chrome_render_frame_); + frame.GetRemoteAssociatedInterfaces()->GetInterface(&chrome_render_frame_); // Watch for the RenderFrameHost being swapped out by a navigation (e.g. after // clicking on a link). In that case, finish the invocation successfully as @@ -285,8 +271,8 @@ // `this` Unretained because the observer is owned by this class and thus // removed on destruction. frame_change_observer_ = std::make_unique<RenderFrameChangeObserver>( - *frame, base::BindOnce(&PageTool::FinishInvoke, base::Unretained(this), - MakeOkResult())); + frame, base::BindOnce(&PageTool::FinishInvoke, base::Unretained(this), + MakeOkResult())); // `this` Unretained because this class owns the mojo pipe that invokes the // callbacks. @@ -308,6 +294,13 @@ } GURL PageTool::JournalURL() const { + if (has_completed_time_of_use_) { + if (RenderFrameHost* frame = GetFrame()) { + return frame->GetLastCommittedURL(); + } else { + return GURL(); + } + } return request_->GetURLForJournal(); } @@ -317,12 +310,14 @@ std::unique_ptr<ObservationDelayController> PageTool::GetObservationDelayer() const { - RenderFrameHost* frame = FindTargetLocalRootFrame( - request_->GetTabHandle(), request_->DocumentIdentifier(), - request_->GetTarget()); + CHECK(has_completed_time_of_use_); + + RenderFrameHost* frame = GetFrame(); + // It's the caller's responsibility to ensure a frame is still live if calling // this method. CHECK(frame); + return std::make_unique<ObservationDelayController>(*frame); } @@ -346,4 +341,9 @@ MakeResult(result_code))); } +content::RenderFrameHost* PageTool::GetFrame() const { + CHECK(has_completed_time_of_use_); + return target_document_.AsRenderFrameHostIfValid(); +} + } // namespace actor
diff --git a/chrome/browser/actor/tools/page_tool.h b/chrome/browser/actor/tools/page_tool.h index 6032223..114f342 100644 --- a/chrome/browser/actor/tools/page_tool.h +++ b/chrome/browser/actor/tools/page_tool.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/memory/safe_ref.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/actor/tools/tool.h" #include "chrome/browser/actor/tools/tool_request.h" @@ -16,6 +17,10 @@ #include "content/public/browser/weak_document_ptr.h" #include "mojo/public/cpp/bindings/associated_remote.h" +namespace content { +class RenderFrameHost; +} // namespace content + namespace actor { class AggregatedJournal; @@ -27,14 +32,16 @@ // of the request to the renderer. class PageTool : public Tool { public: - PageTool(const PageToolRequest& params, AggregatedJournal& journal); + PageTool(TaskId task_id, + AggregatedJournal& journal, + const PageToolRequest& params); ~PageTool() override; // actor::Tool void Validate(ValidateCallback callback) override; mojom::ActionResultPtr TimeOfUseValidation( const optimization_guide::proto::AnnotatedPageContent* last_observation) - const override; + override; void Invoke(InvokeCallback callback) override; std::string DebugString() const override; GURL JournalURL() const override; @@ -47,11 +54,21 @@ void PostFinishInvoke(mojom::ActionResultCode result_code); + content::RenderFrameHost* GetFrame() const; + InvokeCallback invoke_callback_; std::unique_ptr<PageToolRequest> request_; + std::unique_ptr<RenderFrameChangeObserver> frame_change_observer_; mojo::AssociatedRemote<chrome::mojom::ChromeRenderFrame> chrome_render_frame_; + // Whether TimeOfUseValidation has completed. GetFrame can only be queried + // after this has happened. + bool has_completed_time_of_use_ = false; + + // Set during TimeOfUseValidation. + content::WeakDocumentPtr target_document_; + base::WeakPtrFactory<PageTool> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/actor/tools/page_tool_request.cc b/chrome/browser/actor/tools/page_tool_request.cc index 00cf5fd..d90241f 100644 --- a/chrome/browser/actor/tools/page_tool_request.cc +++ b/chrome/browser/actor/tools/page_tool_request.cc
@@ -20,41 +20,42 @@ using optimization_guide::DocumentIdentifierUserData; using tabs::TabHandle; +PageToolRequest::Target::Target(const NodeTarget& node_target) + : impl_(node_target) {} + +PageToolRequest::Target::Target(const CoordinateTarget& coordinate_target) + : impl_(coordinate_target) {} + +PageToolRequest::Target::Target(const Target& other) = default; + +PageToolRequest::Target::~Target() = default; + // static mojom::ToolTargetPtr PageToolRequest::ToMojoToolTarget(const Target& target) { - if (std::holds_alternative<CoordinateTarget>(target)) { - return actor::mojom::ToolTarget::NewCoordinate( - std::get<CoordinateTarget>(target)); + if (target.is_coordinate()) { + return actor::mojom::ToolTarget::NewCoordinate(target.coordinate()); } - NodeTarget node_id = std::get<NodeTarget>(target); - return actor::mojom::ToolTarget::NewDomNodeId( - node_id.value_or(kRootElementDomNodeId)); + CHECK(target.is_node()); + return actor::mojom::ToolTarget::NewDomNodeId(target.node().dom_node_id); } -PageToolRequest::PageToolRequest(TabHandle tab_handle, - std::string_view document_identifier, - const Target& target) - : TabToolRequest(tab_handle), - document_identifier_(document_identifier), - target_(target) {} +PageToolRequest::PageToolRequest(TabHandle tab_handle, const Target& target) + : TabToolRequest(tab_handle), target_(target) {} PageToolRequest::~PageToolRequest() = default; PageToolRequest::PageToolRequest(const PageToolRequest& other) = default; ToolRequest::CreateToolResult PageToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { if (!GetTabHandle().Get()) { return {/*tool=*/nullptr, MakeResult(mojom::ActionResultCode::kTabWentAway, "The tab is no longer present.")}; } - return {std::make_unique<PageTool>(*this, journal), MakeOkResult()}; -} - -const std::optional<std::string>& PageToolRequest::DocumentIdentifier() const { - return document_identifier_; + return {std::make_unique<PageTool>(task_id, journal, *this), MakeOkResult()}; } const PageToolRequest::Target& PageToolRequest::GetTarget() const {
diff --git a/chrome/browser/actor/tools/page_tool_request.h b/chrome/browser/actor/tools/page_tool_request.h index 56c048c..1e49d5d 100644 --- a/chrome/browser/actor/tools/page_tool_request.h +++ b/chrome/browser/actor/tools/page_tool_request.h
@@ -8,6 +8,7 @@ #include <memory> #include <string> #include <string_view> +#include <variant> #include "chrome/browser/actor/tools/tool_request.h" #include "components/tabs/public/tab_interface.h" @@ -21,23 +22,48 @@ // Tool requests targeting a specific, existing document should inherit from // this subclass. Being page-scoped implies also being tab-scoped since a page // exists inside a tab. +// +// Note: A page tool is scoped to a specific (local root) document, however, +// until tool invocation time it isn't valid to dereference the RenderFrameHost +// from the request. This is because the final frame that will be used isn't +// known until the request goes through TimeOfUseValidation and the tool is +// ready to invoke. class PageToolRequest : public TabToolRequest { public: - // Page tool requests must specify a target within the document. This must be - // one of: - // * A coordinate, relative to the local root origin - // * A specific node, specified by DOMNodeId. If not set, targets the root - // element / viewport. - using NodeTarget = std::optional<int>; + // Page tool requests must specify a target in the page. This must be + // one of (mutually exclusive): + // * A main-frame relative coordinate + // * A specific node, specified by DOMNodeId and document identifier pair. + // DOMNodeId can be the kRootElementDomNodeId special value to target the + // viewport. using CoordinateTarget = gfx::Point; - using Target = std::variant<NodeTarget, CoordinateTarget>; + struct NodeTarget { + int dom_node_id; + std::string document_identifier; + }; - // A document identifier is optional if a CoordinateTarget. It is required - // when using a NodeTarget. - // TODO(crbug.com/411462297): Put document identifier into the Target type. - PageToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, - const Target& target); + class Target { + public: + explicit Target(const NodeTarget& node_target); + explicit Target(const CoordinateTarget& coordinate_target); + Target(const Target& other); + ~Target(); + + bool is_coordinate() const { + return std::holds_alternative<CoordinateTarget>(impl_); + } + bool is_node() const { return std::holds_alternative<NodeTarget>(impl_); } + + const CoordinateTarget& coordinate() const { + return std::get<CoordinateTarget>(impl_); + } + const NodeTarget& node() const { return std::get<NodeTarget>(impl_); } + + private: + std::variant<NodeTarget, CoordinateTarget> impl_; + }; + + PageToolRequest(tabs::TabHandle tab_handle, const Target& target); ~PageToolRequest() override; PageToolRequest(const PageToolRequest& other); @@ -48,12 +74,8 @@ virtual std::unique_ptr<PageToolRequest> Clone() const = 0; // ToolRequest - CreateToolResult CreateTool(AggregatedJournal& journal) const override; - - // The provided document identifier in which this request should act. nullopt - // if using coordinates in which case the target document must be hit tested - // from coordinates. - const std::optional<std::string>& DocumentIdentifier() const; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; // Returns what in the page the tool should act upon. const Target& GetTarget() const;
diff --git a/chrome/browser/actor/tools/scroll_tool_request.cc b/chrome/browser/actor/tools/scroll_tool_request.cc index 4ce3de6c..87e5223f 100644 --- a/chrome/browser/actor/tools/scroll_tool_request.cc +++ b/chrome/browser/actor/tools/scroll_tool_request.cc
@@ -11,11 +11,10 @@ using ::tabs::TabHandle; ScrollToolRequest::ScrollToolRequest(TabHandle tab_handle, - std::string_view document_identifier, const Target& target, Direction direction, float distance) - : PageToolRequest(tab_handle, document_identifier, target), + : PageToolRequest(tab_handle, target), direction_(direction), distance_(distance) {}
diff --git a/chrome/browser/actor/tools/scroll_tool_request.h b/chrome/browser/actor/tools/scroll_tool_request.h index a9bc006b..4263881 100644 --- a/chrome/browser/actor/tools/scroll_tool_request.h +++ b/chrome/browser/actor/tools/scroll_tool_request.h
@@ -22,7 +22,6 @@ // If Target is a nullopt ContentNodeId, the root viewport is scrolled. // Distance is specified in physical pixels. ScrollToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, const Target& target, Direction direction, float distance);
diff --git a/chrome/browser/actor/tools/select_tool_request.cc b/chrome/browser/actor/tools/select_tool_request.cc index 5848584b..7c6ff33 100644 --- a/chrome/browser/actor/tools/select_tool_request.cc +++ b/chrome/browser/actor/tools/select_tool_request.cc
@@ -11,10 +11,9 @@ using ::tabs::TabHandle; SelectToolRequest::SelectToolRequest(TabHandle tab_handle, - std::string_view document_identifier, const Target& target, std::string_view value) - : PageToolRequest(tab_handle, document_identifier, target), value_(value) {} + : PageToolRequest(tab_handle, target), value_(value) {} SelectToolRequest::~SelectToolRequest() = default;
diff --git a/chrome/browser/actor/tools/select_tool_request.h b/chrome/browser/actor/tools/select_tool_request.h index 28f1401..bbdf61e 100644 --- a/chrome/browser/actor/tools/select_tool_request.h +++ b/chrome/browser/actor/tools/select_tool_request.h
@@ -19,7 +19,6 @@ class SelectToolRequest : public PageToolRequest { public: SelectToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, const Target& target, std::string_view value); ~SelectToolRequest() override;
diff --git a/chrome/browser/actor/tools/tab_management_tool.cc b/chrome/browser/actor/tools/tab_management_tool.cc index eb88a19..63b1ea6 100644 --- a/chrome/browser/actor/tools/tab_management_tool.cc +++ b/chrome/browser/actor/tools/tab_management_tool.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/actor/tools/tab_management_tool.h" +#include "base/notimplemented.h" #include "chrome/browser/actor/tools/observation_delay_controller.h" #include "chrome/browser/actor/tools/tool_callbacks.h" #include "chrome/browser/ui/browser.h" @@ -22,14 +23,20 @@ using ::tabs::TabHandle; -TabManagementTool::TabManagementTool(int32_t window_id, +TabManagementTool::TabManagementTool(TaskId task_id, + AggregatedJournal& journal, + int32_t window_id, WindowOpenDisposition create_disposition) - : action_(Action::kCreate), + : Tool(task_id, journal), + action_(Action::kCreate), create_disposition_(create_disposition), window_id_(window_id) {} -TabManagementTool::TabManagementTool(Action action, TabHandle tab_handle) - : action_(action), target_tab_(tab_handle) {} +TabManagementTool::TabManagementTool(TaskId task_id, + AggregatedJournal& journal, + Action action, + TabHandle tab_handle) + : Tool(task_id, journal), action_(action), target_tab_(tab_handle) {} TabManagementTool::~TabManagementTool() = default;
diff --git a/chrome/browser/actor/tools/tab_management_tool.h b/chrome/browser/actor/tools/tab_management_tool.h index 0fd1725..4ea8fce 100644 --- a/chrome/browser/actor/tools/tab_management_tool.h +++ b/chrome/browser/actor/tools/tab_management_tool.h
@@ -21,11 +21,16 @@ public: enum Action { kCreate, kActivate, kClose }; - // Public for std::make_unique, use For* static methods above. // Create constructor - TabManagementTool(int32_t window, WindowOpenDisposition create_disposition); + TabManagementTool(TaskId task_id, + AggregatedJournal& journal, + int32_t window, + WindowOpenDisposition create_disposition); // Activate|Close constructor. - TabManagementTool(Action action, tabs::TabHandle target_tab); + TabManagementTool(TaskId task_id, + AggregatedJournal& journal, + Action action, + tabs::TabHandle target_tab); ~TabManagementTool() override;
diff --git a/chrome/browser/actor/tools/tab_management_tool_request.cc b/chrome/browser/actor/tools/tab_management_tool_request.cc index 7174618a..ad7a815 100644 --- a/chrome/browser/actor/tools/tab_management_tool_request.cc +++ b/chrome/browser/actor/tools/tab_management_tool_request.cc
@@ -20,8 +20,10 @@ CreateTabToolRequest::~CreateTabToolRequest() = default; ToolRequest::CreateToolResult CreateTabToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { - return {std::make_unique<TabManagementTool>(window_id_, disposition_), + return {std::make_unique<TabManagementTool>(task_id, journal, window_id_, + disposition_), MakeOkResult()}; } @@ -35,14 +37,15 @@ ActivateTabToolRequest::~ActivateTabToolRequest() = default; ToolRequest::CreateToolResult ActivateTabToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { TabInterface* tab = GetTabHandle().Get(); if (!tab) { return {/*tool=*/nullptr, MakeResult(mojom::ActionResultCode::kTabWentAway, "The tab is no longer present.")}; } - return {std::make_unique<TabManagementTool>(TabManagementTool::kActivate, - GetTabHandle()), + return {std::make_unique<TabManagementTool>( + task_id, journal, TabManagementTool::kActivate, GetTabHandle()), MakeOkResult()}; } @@ -56,14 +59,15 @@ CloseTabToolRequest::~CloseTabToolRequest() = default; ToolRequest::CreateToolResult CloseTabToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { TabInterface* tab = GetTabHandle().Get(); if (!tab) { return {/*tool=*/nullptr, MakeResult(mojom::ActionResultCode::kTabWentAway, "The tab is no longer present.")}; } - return {std::make_unique<TabManagementTool>(TabManagementTool::kClose, - GetTabHandle()), + return {std::make_unique<TabManagementTool>( + task_id, journal, TabManagementTool::kClose, GetTabHandle()), MakeOkResult()}; }
diff --git a/chrome/browser/actor/tools/tab_management_tool_request.h b/chrome/browser/actor/tools/tab_management_tool_request.h index 355970c..b1b2660 100644 --- a/chrome/browser/actor/tools/tab_management_tool_request.h +++ b/chrome/browser/actor/tools/tab_management_tool_request.h
@@ -20,7 +20,8 @@ CreateTabToolRequest(int32_t window_id, WindowOpenDisposition disposition); ~CreateTabToolRequest() override; - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; private: @@ -33,7 +34,8 @@ public: explicit ActivateTabToolRequest(tabs::TabHandle tab); ~ActivateTabToolRequest() override; - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; }; @@ -42,7 +44,8 @@ public: explicit CloseTabToolRequest(tabs::TabHandle tab); ~CloseTabToolRequest() override; - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; };
diff --git a/chrome/browser/actor/tools/tool.cc b/chrome/browser/actor/tools/tool.cc index ea9dcf9..056dfaf 100644 --- a/chrome/browser/actor/tools/tool.cc +++ b/chrome/browser/actor/tools/tool.cc
@@ -4,13 +4,17 @@ #include "chrome/browser/actor/tools/tool.h" +#include "chrome/browser/actor/aggregated_journal.h" #include "chrome/common/actor/action_result.h" namespace actor { +Tool::Tool(TaskId task_id, AggregatedJournal& journal) + : task_id_(task_id), journal_(journal.GetSafeRef()) {} +Tool::~Tool() = default; + mojom::ActionResultPtr Tool::TimeOfUseValidation( - const optimization_guide::proto::AnnotatedPageContent* last_observation) - const { + const optimization_guide::proto::AnnotatedPageContent* last_observation) { // TODO(crbug.com/411462297): This should be made pure-virtual. return MakeOkResult(); }
diff --git a/chrome/browser/actor/tools/tool.h b/chrome/browser/actor/tools/tool.h index b0a5107..6efe4ca 100644 --- a/chrome/browser/actor/tools/tool.h +++ b/chrome/browser/actor/tools/tool.h
@@ -9,7 +9,8 @@ #include <string> #include "base/functional/callback_forward.h" -#include "chrome/browser/actor/aggregated_journal.h" +#include "base/memory/safe_ref.h" +#include "chrome/browser/actor/task_id.h" #include "chrome/common/actor.mojom.h" #include "url/gurl.h" @@ -19,6 +20,7 @@ namespace actor { +class AggregatedJournal; class ObservationDelayController; // Interface all actor tools implement. A tool is held by the ToolController and @@ -30,8 +32,12 @@ // eliminate the other redundant definitions. using ValidateCallback = base::OnceCallback<void(mojom::ActionResultPtr)>; using InvokeCallback = base::OnceCallback<void(mojom::ActionResultPtr)>; - Tool() = default; - virtual ~Tool() = default; + Tool(TaskId task_id, AggregatedJournal& journal); + virtual ~Tool(); + + // Not copyable or movable. + Tool(const Tool& other) = delete; + Tool(Tool&& other) = delete; // Perform any browser-side validation on the tool. The given callback must be // invoked by the tool when validation is completed. If the result given to @@ -46,8 +52,7 @@ // further opportunities for changes to the live browser state before invoking // the tool. virtual mojom::ActionResultPtr TimeOfUseValidation( - const optimization_guide::proto::AnnotatedPageContent* last_observation) - const; + const optimization_guide::proto::AnnotatedPageContent* last_observation); // Perform the action of the tool. The given callback must be invoked when the // tool has finished its actions. @@ -70,6 +75,14 @@ // loading navigation to settle. virtual std::unique_ptr<ObservationDelayController> GetObservationDelayer() const = 0; + + protected: + TaskId task_id() const { return task_id_; } + AggregatedJournal& journal() { return *journal_; } + + private: + TaskId task_id_; + base::SafeRef<AggregatedJournal> journal_; }; } // namespace actor
diff --git a/chrome/browser/actor/tools/tool_controller.cc b/chrome/browser/actor/tools/tool_controller.cc index 9e72466..950c8ff 100644 --- a/chrome/browser/actor/tools/tool_controller.cc +++ b/chrome/browser/actor/tools/tool_controller.cc
@@ -46,7 +46,8 @@ void ToolController::Invoke(const ToolRequest& request, const AnnotatedPageContent* last_observation, ResultCallback result_callback) { - ToolRequest::CreateToolResult create_result = request.CreateTool(*journal_); + ToolRequest::CreateToolResult create_result = + request.CreateTool(task_id_, *journal_); if (!IsOk(*create_result.result)) { CHECK(!create_result.tool);
diff --git a/chrome/browser/actor/tools/tool_request.h b/chrome/browser/actor/tools/tool_request.h index 37f3f592..d6dfaf6 100644 --- a/chrome/browser/actor/tools/tool_request.h +++ b/chrome/browser/actor/tools/tool_request.h
@@ -47,7 +47,8 @@ }; // Instantiates the tool requested by this object. - virtual CreateToolResult CreateTool(AggregatedJournal& journal) const = 0; + virtual CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const = 0; }; // Tool requests targeting a specific, existing tab should inherit from this
diff --git a/chrome/browser/actor/tools/tools_browsertest.cc b/chrome/browser/actor/tools/tools_browsertest.cc index ff064f2d6..d5379fe5 100644 --- a/chrome/browser/actor/tools/tools_browsertest.cc +++ b/chrome/browser/actor/tools/tools_browsertest.cc
@@ -362,7 +362,7 @@ // Send a click to a (0,0) coordinate inside the document. { - BrowserAction action = MakeClick(*main_frame(), gfx::Point(0, 0)); + BrowserAction action = MakeClick(gfx::Point(0, 0)); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); ExpectOkResult(result); @@ -377,7 +377,7 @@ gfx::Point click_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "clickable")); - BrowserAction action = MakeClick(*main_frame(), click_point); + BrowserAction action = MakeClick(click_point); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); ExpectOkResult(result); @@ -401,7 +401,7 @@ // Send a click to a negative coordinate offscreen. { gfx::Point negative_offscreen = {-1, 0}; - BrowserAction action = MakeClick(*main_frame(), negative_offscreen); + BrowserAction action = MakeClick(negative_offscreen); TestFuture<mojom::ActionResultPtr> result_fail; execution_engine().Act(action, result_fail.GetCallback()); ExpectErrorResult(result_fail, @@ -415,7 +415,7 @@ { gfx::Point positive_offscreen = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "offscreen")); - BrowserAction action = MakeClick(*main_frame(), positive_offscreen); + BrowserAction action = MakeClick(positive_offscreen); TestFuture<mojom::ActionResultPtr> result_fail; execution_engine().Act(action, result_fail.GetCallback()); ExpectErrorResult(result_fail, @@ -439,7 +439,7 @@ gfx::Point click_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "offscreen")); - BrowserAction action = MakeClick(*main_frame(), click_point); + BrowserAction action = MakeClick(click_point); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); ExpectOkResult(result); @@ -760,7 +760,7 @@ { gfx::Point type_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "input")); - BrowserAction action = MakeType(*main_frame(), type_point, typed_string, + BrowserAction action = MakeType(type_point, typed_string, /*follow_by_enter=*/true); TestFuture<mojom::ActionResultPtr> result; @@ -774,7 +774,7 @@ { gfx::Point type_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "editableDiv")); - BrowserAction action = MakeType(*main_frame(), type_point, typed_string, + BrowserAction action = MakeType(type_point, typed_string, /*follow_by_enter=*/true); TestFuture<mojom::ActionResultPtr> result; @@ -805,7 +805,7 @@ // Send 'a'. Ensure a click event is observed first on element at the // coordinate. std::string typed_string = "a"; - BrowserAction action = MakeType(*main_frame(), type_point, typed_string, + BrowserAction action = MakeType(type_point, typed_string, /*follow_by_enter=*/false); TestFuture<mojom::ActionResultPtr> result; @@ -832,7 +832,7 @@ // Send 'a'. Ensure a click event is observed first on element at the // coordinate. std::string typed_string = "a"; - BrowserAction action = MakeType(*main_frame(), type_point, typed_string, + BrowserAction action = MakeType(type_point, typed_string, /*follow_by_enter=*/false); TestFuture<mojom::ActionResultPtr> result; @@ -869,7 +869,7 @@ // Send 'a'. Ensure a click event is observed first on element at the // coordinate. std::string typed_string = "a"; - BrowserAction action = MakeType(*main_frame(), type_point, typed_string, + BrowserAction action = MakeType(type_point, typed_string, /*follow_by_enter=*/false); TestFuture<mojom::ActionResultPtr> result; @@ -901,8 +901,8 @@ // Send 'a' to an offscreen coordinate and observe failure. std::string typed_string = "a"; - BrowserAction action = MakeType(*main_frame(), gfx::Point(-1, 0), - typed_string, /*follow_by_enter=*/false); + BrowserAction action = + MakeType(gfx::Point(-1, 0), typed_string, /*follow_by_enter=*/false); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); @@ -1070,7 +1070,7 @@ // Move mouse over #first DIV gfx::Point move_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "first")); - BrowserAction action = MakeMouseMove(*main_frame(), move_point); + BrowserAction action = MakeMouseMove(move_point); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); @@ -1095,7 +1095,7 @@ { gfx::Point move_point = gfx::ToFlooredPoint( GetCenterCoordinatesOfElementWithId(web_contents(), "offscreen")); - BrowserAction action = MakeMouseMove(*main_frame(), move_point); + BrowserAction action = MakeMouseMove(move_point); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); @@ -1460,7 +1460,7 @@ range_rect.y() + thumb_padding); gfx::Point end = gfx::ToFlooredPoint(range_rect.CenterPoint()); - BrowserAction action = MakeDragAndRelease(*main_frame(), start, end); + BrowserAction action = MakeDragAndRelease(start, end); TestFuture<mojom::ActionResultPtr> result_success; execution_engine().Act(action, result_success.GetCallback()); @@ -1491,7 +1491,7 @@ gfx::Point start(target_rect.x() + kPadding, target_rect.y() + kPadding); gfx::Point end = start + delta; - BrowserAction action = MakeDragAndRelease(*main_frame(), start, end); + BrowserAction action = MakeDragAndRelease(start, end); TestFuture<mojom::ActionResultPtr> result_success; execution_engine().Act(action, result_success.GetCallback()); @@ -1523,7 +1523,7 @@ range_rect.y() + thumb_padding); gfx::Point end = gfx::ToFlooredPoint(range_rect.CenterPoint()); - BrowserAction action = MakeDragAndRelease(*main_frame(), start, end); + BrowserAction action = MakeDragAndRelease(start, end); TestFuture<mojom::ActionResultPtr> result; execution_engine().Act(action, result.GetCallback()); ExpectErrorResult(result, @@ -1546,7 +1546,7 @@ range_rect.y() + thumb_padding); gfx::Point end = gfx::ToFlooredPoint(range_rect.CenterPoint()); - BrowserAction action = MakeDragAndRelease(*main_frame(), start, end); + BrowserAction action = MakeDragAndRelease(start, end); TestFuture<mojom::ActionResultPtr> result_success; execution_engine().Act(action, result_success.GetCallback()); ExpectOkResult(result_success);
diff --git a/chrome/browser/actor/tools/type_tool_request.cc b/chrome/browser/actor/tools/type_tool_request.cc index d82e47954..1203982 100644 --- a/chrome/browser/actor/tools/type_tool_request.cc +++ b/chrome/browser/actor/tools/type_tool_request.cc
@@ -11,12 +11,11 @@ using ::tabs::TabHandle; TypeToolRequest::TypeToolRequest(TabHandle tab_handle, - std::string_view document_identifier, const Target& target, std::string_view text, bool follow_by_enter, Mode mode) - : PageToolRequest(tab_handle, document_identifier, target), + : PageToolRequest(tab_handle, target), text(text), follow_by_enter(follow_by_enter), mode(mode) {}
diff --git a/chrome/browser/actor/tools/type_tool_request.h b/chrome/browser/actor/tools/type_tool_request.h index d47aa8b..f52359f 100644 --- a/chrome/browser/actor/tools/type_tool_request.h +++ b/chrome/browser/actor/tools/type_tool_request.h
@@ -27,7 +27,6 @@ }; TypeToolRequest(tabs::TabHandle tab_handle, - std::string_view document_identifier, const Target& target, std::string_view text, bool follow_by_enter,
diff --git a/chrome/browser/actor/tools/wait_tool.cc b/chrome/browser/actor/tools/wait_tool.cc index 4b3f481..24e874d 100644 --- a/chrome/browser/actor/tools/wait_tool.cc +++ b/chrome/browser/actor/tools/wait_tool.cc
@@ -16,8 +16,10 @@ bool WaitTool::no_delay_for_testing_ = false; -WaitTool::WaitTool(base::TimeDelta wait_duration) - : wait_duration_(wait_duration) {} +WaitTool::WaitTool(TaskId task_id, + AggregatedJournal& journal, + base::TimeDelta wait_duration) + : Tool(task_id, journal), wait_duration_(wait_duration) {} WaitTool::~WaitTool() = default;
diff --git a/chrome/browser/actor/tools/wait_tool.h b/chrome/browser/actor/tools/wait_tool.h index 33b30fc..1c3472dc 100644 --- a/chrome/browser/actor/tools/wait_tool.h +++ b/chrome/browser/actor/tools/wait_tool.h
@@ -15,7 +15,9 @@ // Waits for a page to settle before continuing with other tools. class WaitTool : public Tool { public: - explicit WaitTool(base::TimeDelta wait_duration); + explicit WaitTool(TaskId task_id, + AggregatedJournal& journal, + base::TimeDelta wait_duration); ~WaitTool() override; // actor::Tool
diff --git a/chrome/browser/actor/tools/wait_tool_request.cc b/chrome/browser/actor/tools/wait_tool_request.cc index da6ceb3..5a245fa 100644 --- a/chrome/browser/actor/tools/wait_tool_request.cc +++ b/chrome/browser/actor/tools/wait_tool_request.cc
@@ -15,8 +15,10 @@ WaitToolRequest::~WaitToolRequest() = default; ToolRequest::CreateToolResult WaitToolRequest::CreateTool( + TaskId task_id, AggregatedJournal& journal) const { - return {std::make_unique<WaitTool>(wait_duration_), MakeOkResult()}; + return {std::make_unique<WaitTool>(task_id, journal, wait_duration_), + MakeOkResult()}; } std::string WaitToolRequest::JournalEvent() const {
diff --git a/chrome/browser/actor/tools/wait_tool_request.h b/chrome/browser/actor/tools/wait_tool_request.h index ea24cbc6d..7b4b989 100644 --- a/chrome/browser/actor/tools/wait_tool_request.h +++ b/chrome/browser/actor/tools/wait_tool_request.h
@@ -20,7 +20,8 @@ ~WaitToolRequest() override; // ToolRequest - CreateToolResult CreateTool(AggregatedJournal& journal) const override; + CreateToolResult CreateTool(TaskId task_id, + AggregatedJournal& journal) const override; std::string JournalEvent() const override; private:
diff --git a/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/PackageMetrics.java b/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/PackageMetrics.java index 04fd940..1df96930 100644 --- a/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/PackageMetrics.java +++ b/chrome/browser/android/metrics/java/src/org/chromium/chrome/browser/metrics/PackageMetrics.java
@@ -12,8 +12,6 @@ import android.os.storage.StorageManager; import android.os.storage.StorageVolume; -import androidx.annotation.RequiresApi; - import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.metrics.RecordHistogram; @@ -35,7 +33,6 @@ public long cacheSize; } - @RequiresApi(26) private static @Nullable PackageMetricsData getPackageStatsForAndroidO() { Context context = ContextUtils.getApplicationContext(); StorageManager storageManager = context.getSystemService(StorageManager.class);
diff --git a/chrome/browser/ash/boca/DEPS b/chrome/browser/ash/boca/DEPS index fafb713..3106d9c 100644 --- a/chrome/browser/ash/boca/DEPS +++ b/chrome/browser/ash/boca/DEPS
@@ -30,6 +30,7 @@ "+chrome/browser/ui/browser_list_observer.h", "+chrome/browser/ui/browser_navigator.h", "+chrome/browser/ui/browser_window.h", + "+chrome/browser/ui/browser_window/public/browser_window_features.h", "+chrome/browser/ui/exclusive_access/exclusive_access_manager.h", "+chrome/browser/ui/exclusive_access/fullscreen_controller.h", "+chrome/browser/ui/views/frame/browser_view.h",
diff --git a/chrome/browser/ash/boca/on_task/BUILD.gn b/chrome/browser/ash/boca/on_task/BUILD.gn index 4d459e1b..2276dfb 100644 --- a/chrome/browser/ash/boca/on_task/BUILD.gn +++ b/chrome/browser/ash/boca/on_task/BUILD.gn
@@ -43,6 +43,7 @@ "//chrome/browser/extensions", "//chrome/browser/profiles:profile", "//chrome/browser/ui/ash/system_web_apps", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/exclusive_access", "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/views/frame:immersive_mode_controller", @@ -115,6 +116,7 @@ "//chrome/browser/ash/boca", "//chrome/browser/ui:browser_navigator_params_headers", "//chrome/browser/ui/ash/system_web_apps", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/views/frame:immersive_mode_controller", "//chrome/test:test_support", "//chromeos/ash/components/boca",
diff --git a/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl.cc b/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl.cc index 7e87efc..e4afcff 100644 --- a/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl.cc +++ b/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" @@ -143,8 +144,9 @@ // Exit fullscreen mode if necessary. This is especially needed for certain // cases where the web app window is in fullscreen mode but not pinned, like // on session restore. - auto* const fullscreen_controller = - browser->exclusive_access_manager()->fullscreen_controller(); + auto* const fullscreen_controller = browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); if (fullscreen_controller->IsFullscreenForBrowser() && !pinned) { fullscreen_controller->ToggleBrowserFullscreenMode( /*user_initiated=*/false);
diff --git a/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl_browsertest.cc b/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl_browsertest.cc index 3d1a9f78..30802fb 100644 --- a/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl_browsertest.cc +++ b/chrome/browser/ash/boca/on_task/on_task_system_web_app_manager_impl_browsertest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -248,8 +249,9 @@ ASSERT_THAT(boca_app_browser, NotNull()); // Toggle fullscreen mode but do not pin the window. - auto* const fullscreen_controller = - boca_app_browser->exclusive_access_manager()->fullscreen_controller(); + auto* const fullscreen_controller = boca_app_browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); fullscreen_controller->ToggleBrowserFullscreenMode(/*user_initiated=*/false); ASSERT_TRUE(fullscreen_controller->IsFullscreenForBrowser());
diff --git a/chrome/browser/ash/login/BUILD.gn b/chrome/browser/ash/login/BUILD.gn index 526ff45..8fd741a 100644 --- a/chrome/browser/ash/login/BUILD.gn +++ b/chrome/browser/ash/login/BUILD.gn
@@ -445,6 +445,7 @@ "//chrome/browser/ui/ash/login", "//chrome/browser/ui/ash/login:test_support", "//chrome/browser/ui/ash/shell_delegate", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/webui/ash/system_web_dialog", "//chrome/browser/ui/webui/signin", "//chrome/browser/ui/webui/signin:signin_utils",
diff --git a/chrome/browser/ash/login/DEPS b/chrome/browser/ash/login/DEPS index fe4259f..4a45888 100644 --- a/chrome/browser/ash/login/DEPS +++ b/chrome/browser/ash/login/DEPS
@@ -144,6 +144,7 @@ "+chrome/browser/ui/browser_navigator_params.h", "+chrome/browser/ui/browser_tabstrip.h", "+chrome/browser/ui/browser_window.h", + "+chrome/browser/ui/browser_window/public/browser_window_features.h", "+chrome/browser/ui/test", "+chrome/test/base", "+chrome/test/interaction",
diff --git a/chrome/browser/ash/login/guest_login_browsertest.cc b/chrome/browser/ash/login/guest_login_browsertest.cc index 1b67eb3..24ea9ca4a 100644 --- a/chrome/browser/ash/login/guest_login_browsertest.cc +++ b/chrome/browser/ash/login/guest_login_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/webui/ash/login/guest_tos_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/user_creation_screen_handler.h" @@ -207,7 +208,8 @@ login_manager_.WaitForActiveSession(); BrowserWindow* browser_window = browser()->window(); browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ToggleBrowserFullscreenMode(/*user_initiated=*/true); EXPECT_TRUE(browser_window->IsFullscreen());
diff --git a/chrome/browser/ash/login/lock/BUILD.gn b/chrome/browser/ash/login/lock/BUILD.gn index f7134e3..973e70b 100644 --- a/chrome/browser/ash/login/lock/BUILD.gn +++ b/chrome/browser/ash/login/lock/BUILD.gn
@@ -152,6 +152,7 @@ "//chrome/browser/ash/policy/core:test_support", "//chrome/browser/ui", "//chrome/browser/ui/ash/login", + "//chrome/browser/ui/browser_window", "//chrome/test:test_support_ui", "//chromeos/ash/components/dbus/biod", "//chromeos/ash/components/dbus/session_manager",
diff --git a/chrome/browser/ash/login/lock/screen_locker_browsertest.cc b/chrome/browser/ash/login/lock/screen_locker_browsertest.cc index 76f0080f..ff37590 100644 --- a/chrome/browser/ash/login/lock/screen_locker_browsertest.cc +++ b/chrome/browser/ash/login/lock/screen_locker_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/ash/login/user_adding_screen.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/test/base/in_process_browser_test.h" @@ -150,7 +151,8 @@ browser()->tab_strip_model()->GetActiveWebContents(); ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true}); browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame()); waiter.Wait();
diff --git a/chrome/browser/ash/system_web_apps/apps/BUILD.gn b/chrome/browser/ash/system_web_apps/apps/BUILD.gn index 43b6f47..4472413b 100644 --- a/chrome/browser/ash/system_web_apps/apps/BUILD.gn +++ b/chrome/browser/ash/system_web_apps/apps/BUILD.gn
@@ -258,6 +258,8 @@ "//chrome/browser/ui", "//chrome/browser/ui/ash/system_web_apps", "//chrome/browser/ui/web_applications", + "//chrome/browser/ui/webui/ash/diagnostics_dialog", + "//chrome/browser/ui/webui/ash/system_web_dialog", "//chrome/browser/web_applications", "//chrome/browser/web_applications:web_applications_test_support", "//chrome/common:constants",
diff --git a/chrome/browser/ash/system_web_apps/apps/diagnostics_app_integration_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/diagnostics_app_integration_browsertest.cc index 2be39af..f532499 100644 --- a/chrome/browser/ash/system_web_apps/apps/diagnostics_app_integration_browsertest.cc +++ b/chrome/browser/ash/system_web_apps/apps/diagnostics_app_integration_browsertest.cc
@@ -4,11 +4,15 @@ #include "ash/webui/diagnostics_ui/url_constants.h" #include "ash/webui/system_apps/public/system_web_app_type.h" +#include "ash/wm/window_pin_util.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/run_until.h" #include "chrome/browser/ash/system_web_apps/test_support/system_web_app_integration_test.h" #include "chrome/browser/lifetime/application_lifetime_desktop.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h" +#include "chrome/browser/ui/webui/ash/system_web_dialog/system_web_dialog_delegate.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -38,6 +42,11 @@ public: DiagnosticsAppIntegrationTest() = default; + static bool IsDiagnosticsDialogVisible() { + return ash::SystemWebDialogDelegate::HasInstance( + GURL("chrome://diagnostics")); + } + protected: base::HistogramTester histogram_tester_; @@ -210,5 +219,16 @@ .ExtractBool()); } +IN_PROC_BROWSER_TEST_P(DiagnosticsAppIntegrationTest, + DiagnosticsDialogClosesForLockedFullscreen) { + ash::DiagnosticsDialog::ShowDialog(); + EXPECT_TRUE(IsDiagnosticsDialogVisible()); + + // Enter locked fullscreen. + PinWindow(browser()->window()->GetNativeWindow(), /*trusted=*/true); + EXPECT_TRUE( + base::test::RunUntil([&]() { return !IsDiagnosticsDialogVisible(); })); +} + INSTANTIATE_SYSTEM_WEB_APP_MANAGER_TEST_SUITE_REGULAR_PROFILE_P( DiagnosticsAppIntegrationTest);
diff --git a/chrome/browser/autofill/ui/autofill_image_fetcher_impl.cc b/chrome/browser/autofill/ui/autofill_image_fetcher_impl.cc index 26882fee..fb48c9f 100644 --- a/chrome/browser/autofill/ui/autofill_image_fetcher_impl.cc +++ b/chrome/browser/autofill/ui/autofill_image_fetcher_impl.cc
@@ -91,7 +91,7 @@ // Pay with Pix is only queried in Chrome on Android. NOTREACHED(); case ImageType::kValuableImage: - return GURL(image_url.spec() + "=h24-w24-cc-rp"); + return GURL(image_url.spec() + "=h96-w96-cc-rp"); } } @@ -141,6 +141,15 @@ gfx::ImageSkia::CreateFromBitmap(canvas.GetBitmap(), 1.0f))); } +gfx::Image AutofillImageFetcherImpl::ResolveValuableImage( + const gfx::Image& valuable_image) { + // Increase image scale from 1.0 to 4.0 to render higher quality images on + // high resolution displays. This decreases the image size from 96x96 to + // 24x24. + return gfx::Image( + gfx::ImageSkia::CreateFromBitmap(valuable_image.AsBitmap(), 4.0f)); +} + // static gfx::Image AutofillImageFetcherImpl::ApplyGreyOverlay(const gfx::Image& image) { // Create a solid dark grey mask for the image.
diff --git a/chrome/browser/autofill/ui/autofill_image_fetcher_impl.h b/chrome/browser/autofill/ui/autofill_image_fetcher_impl.h index 3b4a908..93d1a2d1 100644 --- a/chrome/browser/autofill/ui/autofill_image_fetcher_impl.h +++ b/chrome/browser/autofill/ui/autofill_image_fetcher_impl.h
@@ -32,6 +32,7 @@ // AutofillImageFetcher: gfx::Image ResolveCardArtImage(const GURL& card_art_url, const gfx::Image& card_art_image) override; + gfx::Image ResolveValuableImage(const gfx::Image& valuable_image) override; // The image fetcher attached. raw_ptr<image_fetcher::ImageFetcher> image_fetcher_ = nullptr;
diff --git a/chrome/browser/autofill/ui/autofill_image_fetcher_impl_unittest.cc b/chrome/browser/autofill/ui/autofill_image_fetcher_impl_unittest.cc index 2da0542..d54ed0b 100644 --- a/chrome/browser/autofill/ui/autofill_image_fetcher_impl_unittest.cc +++ b/chrome/browser/autofill/ui/autofill_image_fetcher_impl_unittest.cc
@@ -53,8 +53,8 @@ } TEST_F(AutofillImageFetcherImplTest, ResolveValuableImageURL) { - // Valuable images are resized to (24x24) and cropped. - EXPECT_EQ(GURL("https://www.example.com/fake_image1=h24-w24-cc-rp"), + // Valuable images are resized to (96x96) and cropped. + EXPECT_EQ(GURL("https://www.example.com/fake_image1=h96-w96-cc-rp"), autofill_image_fetcher()->ResolveImageURL( GURL("https://www.example.com/fake_image1"), AutofillImageFetcherBase::ImageType::kValuableImage));
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc index 7b6608b..b88170e 100644 --- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc +++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils.cc
@@ -7,6 +7,7 @@ #include <string> #include <vector> +#include "base/feature_list.h" #include "base/i18n/number_formatting.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -17,6 +18,7 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" +#include "components/browsing_data/core/features.h" #include "components/browsing_data/core/pref_names.h" #include "components/prefs/pref_service.h" #include "components/signin/public/base/consent_level.h" @@ -29,6 +31,10 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) +#include "ui/strings/grit/ui_strings.h" +#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) + #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/browsing_data/counters/tabs_counter.h" #endif @@ -171,6 +177,26 @@ is_signed_in = true; } } + +#if !BUILDFLAG(IS_CHROMEOS) + if (base::FeatureList::IsEnabled( + browsing_data::features::kDbdRevampDesktop)) { + std::u16string cookies_counter_text = l10n_util::GetPluralStringFUTF16( + IDS_DEL_COOKIES_COUNTER_ADVANCED, origins); + + if (origins > 0 && + (ShouldShowCookieException(profile) || + (is_signed_in && + signin::AreGoogleCookiesRebuiltAfterClearingWhenSignedIn( + *identity_manager, *profile->GetPrefs())))) { + cookies_counter_text += + (l10n_util::GetStringUTF16(IDS_SENTENCE_END) + u" " + + l10n_util::GetStringUTF16(IDS_DEL_GOOGLE_COOKIES_SIGNOUT_LINK)); + } + return cookies_counter_text; + } +#endif // !BUILDFLAG(IS_CHROMEOS) + int del_cookie_counter_msg_id = ShouldShowCookieException(profile) || (is_signed_in &&
diff --git a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc index a637048..a9491d1 100644 --- a/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc +++ b/chrome/browser/browsing_data/counters/browsing_data_counter_utils_unittest.cc
@@ -9,6 +9,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/browsing_data/counters/cache_counter.h" #include "chrome/browser/browsing_data/counters/signin_data_counter.h" @@ -17,6 +18,7 @@ #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "components/browsing_data/core/features.h" #include "components/password_manager/core/browser/password_store/test_password_store.h" #include "components/prefs/pref_service.h" #include "components/signin/public/base/consent_level.h" @@ -339,8 +341,9 @@ }; struct TestCase { + int num_sites; SigninState signin_state = SigninState::kSignedOut; - bool expects_exception_text = false; + std::string expected_output; }; void SetSignedOutState(syncer::TestSyncService* test_sync_service) { @@ -409,7 +412,8 @@ } void VerifyTestCase(const TestCase& test_case) { - SCOPED_TRACE(base::StringPrintf("Test params: %d signin_state.", + SCOPED_TRACE(base::StringPrintf("Test params: %d site(s), %d signin_state.", + test_case.num_sites, static_cast<int>(test_case.signin_state))); // Setup the signin state. std::unique_ptr<TestingProfile> testing_profile = @@ -464,56 +468,69 @@ browsing_data::ClearBrowsingDataTab::ADVANCED, browsing_data::BrowsingDataCounter::ResultCallback()); - browsing_data::BrowsingDataCounter::FinishedResult result0(&counter, 0); - EXPECT_EQ(GetChromeCounterTextFromResult(&result0, testing_profile.get()), - u"None"); - - browsing_data::BrowsingDataCounter::FinishedResult result1(&counter, 1); - browsing_data::BrowsingDataCounter::FinishedResult result42(&counter, 42); - std::u16string output1 = - GetChromeCounterTextFromResult(&result1, testing_profile.get()); - std::u16string output42 = - GetChromeCounterTextFromResult(&result42, testing_profile.get()); - if (test_case.expects_exception_text) { - EXPECT_EQ(output1, - u"From 1 site (you'll stay signed in to your Google Account)"); - EXPECT_EQ( - output42, - u"From 42 sites (you'll stay signed in to your Google Account)"); - } else { - EXPECT_EQ(output1, u"From 1 site "); - EXPECT_EQ(output42, u"From 42 sites "); - } + browsing_data::BrowsingDataCounter::FinishedResult result( + &counter, test_case.num_sites); + std::u16string output = + GetChromeCounterTextFromResult(&result, testing_profile.get()); + EXPECT_EQ(output, base::ASCIIToUTF16(test_case.expected_output)); } }; - TEST_F(CookieBrowsingDataCounterUtilsTest, CookieCounterResult) { - // This test assumes that the strings are served exactly as defined, - // i.e. that the locale is set to the default "en". + // This test assumes that the strings are served exactly as defined, i.e. that + // the locale is set to the default "en". ASSERT_EQ("en", TestingBrowserProcess::GetGlobal()->GetApplicationLocale()); // Test the output for various forms of cookie results. const struct TestCase kTestCases[] = { - {.signin_state = SigninState::kSignedOut, - .expects_exception_text = false}, - {.signin_state = SigninState::kAccountAware, - .expects_exception_text = false}, - {.signin_state = SigninState::kImplicitSignin, - .expects_exception_text = false}, - {.signin_state = SigninState::kExplicitSignin, - .expects_exception_text = true}, - {.signin_state = SigninState::kSigninPending, - .expects_exception_text = false}, - {.signin_state = SigninState::kSyncing, .expects_exception_text = true}, - {.signin_state = SigninState::kSyncPaused, - .expects_exception_text = false}, + {/*num_sites= */ 0, SigninState::kSignedOut, "None"}, + {/*num_sites= */ 1, SigninState::kSignedOut, "From 1 site"}, + {/*num_sites= */ 42, SigninState::kAccountAware, "From 42 sites"}, + {/*num_sites= */ 1, SigninState::kImplicitSignin, "From 1 site"}, + {/*num_sites= */ 5, SigninState::kSigninPending, "From 5 sites"}, + {/*num_sites= */ 10, SigninState::kSyncPaused, "From 10 sites"}, + {/*num_sites= */ 1, SigninState::kExplicitSignin, + "From 1 site (you'll stay signed in to your Google Account)"}, + {/*num_sites= */ 42, SigninState::kSyncing, + "From 42 sites (you'll stay signed in to your Google Account)"}, + {/*num_sites= */ 0, SigninState::kSyncing, "None"}, }; for (const TestCase& test_case : kTestCases) { VerifyTestCase(test_case); } } + +TEST_F(CookieBrowsingDataCounterUtilsTest, CookieCounterResult_RevampEnabled) { + base::test::ScopedFeatureList feature( + browsing_data::features::kDbdRevampDesktop); + // This test assumes that the strings are served exactly as defined, i.e. that + // the locale is set to the default "en". + ASSERT_EQ("en", TestingBrowserProcess::GetGlobal()->GetApplicationLocale()); + + // Test the output for various forms of cookie results. + const struct TestCase kTestCases[] = { + {/*num_sites= */ 0, SigninState::kSignedOut, "None"}, + {/*num_sites= */ 1, SigninState::kSignedOut, "From 1 site"}, + {/*num_sites= */ 42, SigninState::kAccountAware, "From 42 sites"}, + {/*num_sites= */ 1, SigninState::kImplicitSignin, "From 1 site"}, + {/*num_sites= */ 5, SigninState::kSigninPending, "From 5 sites"}, + {/*num_sites= */ 10, SigninState::kSyncPaused, "From 10 sites"}, + {/*num_sites= */ 1, SigninState::kExplicitSignin, + "From 1 site. To delete Google cookies from this device, <a href=\"#\" " + "target=\"_blank\" id=\"signOutLink\">sign out of Chrome</a>."}, + {/*num_sites= */ 42, SigninState::kSyncing, + "From 42 sites. To delete Google cookies from this device, <a " + "href=\"#\" target=\"_blank\" id=\"signOutLink\">sign out of " + "Chrome</a>."}, + {/*num_sites= */ 0, SigninState::kSyncing, "None"}, + }; + + for (const TestCase& test_case : kTestCases) { + VerifyTestCase(test_case); + } +} + #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) } // namespace browsing_data_counter_utils
diff --git a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc index 81bb210..b665fb8 100644 --- a/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc +++ b/chrome/browser/chrome_web_platform_security_metrics_browsertest.cc
@@ -271,7 +271,8 @@ content::JsReplace("fetch($1).then(response => response.ok)", https_server().GetURL("b.com", kPnaPath)))); - CheckCounter(WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, 1); + CheckCounter(WebFeature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, + 1); CheckCounter(WebFeature::kPrivateNetworkAccessPreflightSuccess, 1); } @@ -298,7 +299,8 @@ "fetch($1).then(response => response.ok)", https_server().GetURL("b.com", "/cors-ok.txt")))); - CheckCounter(WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, 1); + CheckCounter(WebFeature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, + 1); CheckCounter(WebFeature::kPrivateNetworkAccessPreflightWarning, 1); }
diff --git a/chrome/browser/chromeos/app_mode/BUILD.gn b/chrome/browser/chromeos/app_mode/BUILD.gn index fc06c3e..ff22858 100644 --- a/chrome/browser/chromeos/app_mode/BUILD.gn +++ b/chrome/browser/chromeos/app_mode/BUILD.gn
@@ -129,6 +129,7 @@ "//chrome/browser/ui", "//chrome/browser/ui/apps", "//chrome/browser/ui/ash/system_web_apps", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/exclusive_access", "//chrome/browser/ui/tabs:test_support", "//chrome/browser/web_applications",
diff --git a/chrome/browser/chromeos/app_mode/DEPS b/chrome/browser/chromeos/app_mode/DEPS index 63fd5c9b..c2ad119 100644 --- a/chrome/browser/chromeos/app_mode/DEPS +++ b/chrome/browser/chromeos/app_mode/DEPS
@@ -79,6 +79,7 @@ "+chrome/browser/ash/system_web_apps/system_web_app_manager.h", "+chrome/browser/ash/system_web_apps/test_support/test_system_web_app_installation.h", "+chrome/browser/ash/system_web_apps/test_support/test_system_web_app_manager.h", + "+chrome/browser/ui/browser_window/public/browser_window_features.h", "+chromeos/ash/experiences/system_web_apps/types/system_web_app_delegate_map.h", ], }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc index f3a5485a3b..5061cbef 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc
@@ -44,6 +44,7 @@ #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/tabs/tab_activity_simulator.h" @@ -131,7 +132,8 @@ bool IsClosed() { return closed_future_.IsReady(); } bool IsFullscreen() { - return browser_->exclusive_access_manager() + return browser_->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsFullscreenForBrowser(); }
diff --git a/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java b/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java index 09b04e3c..a134360b 100644 --- a/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java +++ b/chrome/browser/commerce/coupons/android/javatests/src/org/chromium/chrome/browser/commerce/coupons/DiscountsBottomSheetContentRenderTest.java
@@ -13,7 +13,6 @@ import static org.chromium.ui.test.util.RenderTestRule.Component.UI_BROWSER_SHOPPING; import android.app.Activity; -import android.os.Build.VERSION_CODES; import android.view.View; import androidx.recyclerview.widget.RecyclerView; @@ -32,7 +31,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.tab.Tab; @@ -95,7 +93,6 @@ @Test @SmallTest @Feature({"RenderTest"}) - @DisableIf.Build(sdk_is_less_than = VERSION_CODES.P, message = "crbug.com/382335140") public void testSingleDiscountContent() throws IOException { ThreadUtils.runOnUiThreadBlocking( () -> { @@ -114,7 +111,6 @@ @Test @SmallTest @Feature({"RenderTest"}) - @DisableIf.Build(sdk_is_less_than = VERSION_CODES.P, message = "crbug.com/382335140") public void testMultipleDiscountsContents() throws IOException { ThreadUtils.runOnUiThreadBlocking( () -> {
diff --git a/chrome/browser/composeplate/android/java/src/org/chromium/chrome/browser/composeplate/ComposeplateMetricsUtils.java b/chrome/browser/composeplate/android/java/src/org/chromium/chrome/browser/composeplate/ComposeplateMetricsUtils.java index dc503ee8..1f53ff8 100644 --- a/chrome/browser/composeplate/android/java/src/org/chromium/chrome/browser/composeplate/ComposeplateMetricsUtils.java +++ b/chrome/browser/composeplate/android/java/src/org/chromium/chrome/browser/composeplate/ComposeplateMetricsUtils.java
@@ -41,7 +41,11 @@ BrowserUiUtils.recordModuleClickHistogram(ModuleTypeOnStartAndNtp.COMPOSEPLATE_BUTTON); } - /** Records an impression of the fake search box on the New Tab Page. */ + /** + * Records an impression of the fake search box on the New Tab Page. This logs a baseline + * impression count for the button in the fake search box. The event is triggered each time the + * New Tab Page is shown or the button's visibility is updated. + */ public static void recordFakeSearchBoxImpression() { RecordHistogram.recordCount100Histogram(HISTOGRAM_NTP_OMNIBOX_IMPRESSION, 1); }
diff --git a/chrome/browser/devtools/BUILD.gn b/chrome/browser/devtools/BUILD.gn index 220475f4..dc6aaa7 100644 --- a/chrome/browser/devtools/BUILD.gn +++ b/chrome/browser/devtools/BUILD.gn
@@ -326,6 +326,7 @@ deps += [ "//chrome/app:command_ids", "//chrome/browser/first_party_sets", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/media_router", "//components/custom_handlers", "//components/media_router/browser",
diff --git a/chrome/browser/devtools/protocol/target_handler.cc b/chrome/browser/devtools/protocol/target_handler.cc index 1f62892..222bcd4 100644 --- a/chrome/browser/devtools/protocol/target_handler.cc +++ b/chrome/browser/devtools/protocol/target_handler.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/common/webui_url_constants.h" @@ -214,7 +215,8 @@ } else if (*window_state == protocol::Target::WindowStateEnum::Maximized) { params.browser->window()->Maximize(); } else if (*window_state == protocol::Target::WindowStateEnum::Fullscreen) { - params.browser->exclusive_access_manager() + params.browser->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ToggleBrowserFullscreenMode(/*user_initiated=*/false); } else {
diff --git a/chrome/browser/download/bubble/download_bubble_prefs.cc b/chrome/browser/download/bubble/download_bubble_prefs.cc index 54e28c8..648526b 100644 --- a/chrome/browser/download/bubble/download_bubble_prefs.cc +++ b/chrome/browser/download/bubble/download_bubble_prefs.cc
@@ -7,6 +7,7 @@ #include "base/feature_list.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" +#include "chrome/browser/headless/headless_mode_util.h" #include "chrome/common/pref_names.h" #include "components/enterprise/buildflags/buildflags.h" #include "components/prefs/pref_service.h" @@ -29,6 +30,11 @@ } bool ShouldShowDownloadBubble(Profile* profile) { + // There is no need to display download bubble in headless mode. This prevents + // http://crbug.com/379994807 but also makes sense on other platforms. + if (headless::IsHeadlessMode()) { + return false; + } // If the download UI is disabled by at least one extension, do not show the // bubble and the toolbar icon. return DownloadCoreServiceFactory::GetForBrowserContext(
diff --git a/chrome/browser/download/bubble/download_display_controller.cc b/chrome/browser/download/bubble/download_display_controller.cc index 26b338b..0b43da5 100644 --- a/chrome/browser/download/bubble/download_display_controller.cc +++ b/chrome/browser/download/bubble/download_display_controller.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/download/download_item_mode.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" @@ -118,7 +119,8 @@ if (display_->ShouldShowExclusiveAccessBubble()) { fullscreen_notification_shown_ = true; // ExclusiveAccessContext can be null in tests. - if (auto* context = browser_->exclusive_access_manager()->context()) { + if (auto* context = + browser_->GetFeatures().exclusive_access_manager()->context()) { context->UpdateExclusiveAccessBubble( {.has_download = true, .force_update = true}, base::NullCallback()); } @@ -215,8 +217,9 @@ } void DownloadDisplayController::ListenToFullScreenChanges() { - observation_.Observe( - browser_->exclusive_access_manager()->fullscreen_controller()); + observation_.Observe(browser_->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller()); } void DownloadDisplayController::OnFullscreenStateChanged() {
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_features.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_features.cc index c739511..3fd9346 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_features.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_features.cc
@@ -36,4 +36,8 @@ "max_file_size_mb", /*default_value=*/50); +// Controls whether encrypted file upload is enabled. +BASE_FEATURE(kEnableEncryptedFileUpload, + "EnableEncryptedFileUpload", + base::FEATURE_DISABLED_BY_DEFAULT); } // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_features.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_features.h index 7bb8e1ac..7c3a3487 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_features.h +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_features.h
@@ -26,6 +26,9 @@ // Controls the maximum file size for content analysis in MB. BASE_DECLARE_FEATURE_PARAM(size_t, kMaxContentAnalysisFileSizeMB); +// Controls whether encrypted file upload is enabled. +BASE_DECLARE_FEATURE(kEnableEncryptedFileUpload); + } // namespace enterprise_connectors #endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_FEATURES_H_
diff --git a/chrome/browser/enterprise/connectors/reporting/reporting_event_router_unittest.cc b/chrome/browser/enterprise/connectors/reporting/reporting_event_router_unittest.cc index 8fc6ae1..a316c4ab 100644 --- a/chrome/browser/enterprise/connectors/reporting/reporting_event_router_unittest.cc +++ b/chrome/browser/enterprise/connectors/reporting/reporting_event_router_unittest.cc
@@ -336,28 +336,32 @@ } TEST_P(ReportingEventRouterTest, TestOnUrlFilteringInterstitial_Blocked) { - // TODO(crbug.com/396439420): Migrate url filtering event to proto format. - if (use_proto_format()) { - return; - } EnableEnhancedFieldsForSecOps(); test::SetOnSecurityEventReporting( profile_->GetPrefs(), /*enabled=*/true, /*enabled_event_names=*/{kKeyUrlFilteringInterstitialEvent}, /*enabled_opt_in_events=*/{}); + test::EventReportValidatorBase validator(client_.get()); chrome::cros::reporting::proto::UrlFilteringInterstitialEvent expected_event; + expected_event.set_url("https://filteredurl.com/"); expected_event.set_event_result( chrome::cros::reporting::proto::EVENT_RESULT_BLOCKED); + expected_event.set_threat_type( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent:: + ENTERPRISE_BLOCKED_SEEN); expected_event.set_profile_user_name(profile_->GetProfileUserName()); expected_event.set_profile_identifier(GetProfileIdentifier()); *expected_event.add_triggered_rule_info() = test::MakeTriggeredRuleInfo( /*action=*/TriggeredRuleInfo::BLOCK, /*has_watermark=*/false); *expected_event.add_referrers() = test::MakeUrlInfoReferrer(); - test::EventReportValidatorBase validator(client_.get()); - validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + if (use_proto_format()) { + validator.ExpectProtoBasedUrlFilteringInterstitialEvent(expected_event); + } else { + validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + } safe_browsing::RTLookupResponse response; auto* threat_info = response.add_threat_info(); @@ -368,36 +372,41 @@ matched_url_navigation_rule->set_rule_id("123"); matched_url_navigation_rule->set_rule_name("test rule name"); matched_url_navigation_rule->set_matched_url_category("test rule category"); - ReferrerChain referrer_chain; + ReferrerChain referrer_chain; + referrer_chain.Add(test::MakeReferrerChainEntry()); reporting_event_router_->OnUrlFilteringInterstitial( GURL("https://filteredurl.com"), "ENTERPRISE_BLOCKED_SEEN", response, referrer_chain); } TEST_P(ReportingEventRouterTest, TestOnUrlFilteringInterstitial_Warned) { - // TODO(crbug.com/396439420): Migrate url filtering event to proto format. - if (use_proto_format()) { - return; - } EnableEnhancedFieldsForSecOps(); test::SetOnSecurityEventReporting( profile_->GetPrefs(), /*enabled=*/true, /*enabled_event_names=*/{kKeyUrlFilteringInterstitialEvent}, /*enabled_opt_in_events=*/{}); + test::EventReportValidatorBase validator(client_.get()); chrome::cros::reporting::proto::UrlFilteringInterstitialEvent expected_event; + expected_event.set_url("https://filteredurl.com/"); expected_event.set_event_result( chrome::cros::reporting::proto::EVENT_RESULT_WARNED); + expected_event.set_threat_type( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent:: + ENTERPRISE_WARNED_SEEN); expected_event.set_profile_user_name(profile_->GetProfileUserName()); expected_event.set_profile_identifier(GetProfileIdentifier()); *expected_event.add_triggered_rule_info() = test::MakeTriggeredRuleInfo( /*action=*/TriggeredRuleInfo::WARN, /*has_watermark=*/true); *expected_event.add_referrers() = test::MakeUrlInfoReferrer(); - test::EventReportValidatorBase validator(client_.get()); - validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + if (use_proto_format()) { + validator.ExpectProtoBasedUrlFilteringInterstitialEvent(expected_event); + } else { + validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + } safe_browsing::RTLookupResponse response; auto* threat_info = response.add_threat_info(); @@ -410,36 +419,42 @@ matched_url_navigation_rule->set_matched_url_category("test rule category"); matched_url_navigation_rule->mutable_watermark_message() ->set_watermark_message("watermark message"); - ReferrerChain referrer_chain; + ReferrerChain referrer_chain; + referrer_chain.Add(test::MakeReferrerChainEntry()); reporting_event_router_->OnUrlFilteringInterstitial( GURL("https://filteredurl.com"), "ENTERPRISE_WARNED_SEEN", response, referrer_chain); } TEST_P(ReportingEventRouterTest, TestOnUrlFilteringInterstitial_Bypassed) { - // TODO(crbug.com/396439420): Migrate url filtering event to proto format. - if (use_proto_format()) { - return; - } EnableEnhancedFieldsForSecOps(); test::SetOnSecurityEventReporting( profile_->GetPrefs(), /*enabled=*/true, /*enabled_event_names=*/{kKeyUrlFilteringInterstitialEvent}, /*enabled_opt_in_events=*/{}); + test::EventReportValidatorBase validator(client_.get()); chrome::cros::reporting::proto::UrlFilteringInterstitialEvent expected_event; + expected_event.set_url("https://filteredurl.com/"); expected_event.set_event_result( chrome::cros::reporting::proto::EVENT_RESULT_BYPASSED); + expected_event.set_clicked_through(true); + expected_event.set_threat_type( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent:: + ENTERPRISE_WARNED_BYPASS); expected_event.set_profile_user_name(profile_->GetProfileUserName()); expected_event.set_profile_identifier(GetProfileIdentifier()); *expected_event.add_triggered_rule_info() = test::MakeTriggeredRuleInfo( /*action=*/TriggeredRuleInfo::WARN, /*has_watermark=*/true); *expected_event.add_referrers() = test::MakeUrlInfoReferrer(); - test::EventReportValidatorBase validator(client_.get()); - validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + if (use_proto_format()) { + validator.ExpectProtoBasedUrlFilteringInterstitialEvent(expected_event); + } else { + validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + } safe_browsing::RTLookupResponse response; auto* threat_info = response.add_threat_info(); @@ -452,8 +467,9 @@ matched_url_navigation_rule->set_matched_url_category("test rule category"); matched_url_navigation_rule->mutable_watermark_message() ->set_watermark_message("confidential"); - ReferrerChain referrer_chain; + ReferrerChain referrer_chain; + referrer_chain.Add(test::MakeReferrerChainEntry()); reporting_event_router_->OnUrlFilteringInterstitial( GURL("https://filteredurl.com"), "ENTERPRISE_WARNED_BYPASS", response, referrer_chain); @@ -461,28 +477,32 @@ TEST_P(ReportingEventRouterTest, TestOnUrlFilteringInterstitial_WatermarkAudit) { - // TODO(crbug.com/396439420): Migrate url filtering event to proto format. - if (use_proto_format()) { - return; - } EnableEnhancedFieldsForSecOps(); test::SetOnSecurityEventReporting( profile_->GetPrefs(), /*enabled=*/true, /*enabled_event_names=*/{kKeyUrlFilteringInterstitialEvent}, /*enabled_opt_in_events=*/{}); + test::EventReportValidatorBase validator(client_.get()); chrome::cros::reporting::proto::UrlFilteringInterstitialEvent expected_event; + expected_event.set_url("https://filteredurl.com/"); expected_event.set_event_result( chrome::cros::reporting::proto::EVENT_RESULT_ALLOWED); + expected_event.set_threat_type( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent:: + UNKNOWN_INTERSTITIAL_THREAT_TYPE); expected_event.set_profile_user_name(profile_->GetProfileUserName()); expected_event.set_profile_identifier(GetProfileIdentifier()); *expected_event.add_triggered_rule_info() = test::MakeTriggeredRuleInfo( /*action=*/TriggeredRuleInfo::ACTION_UNKNOWN, /*has_watermark=*/true); *expected_event.add_referrers() = test::MakeUrlInfoReferrer(); - test::EventReportValidatorBase validator(client_.get()); - validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + if (use_proto_format()) { + validator.ExpectProtoBasedUrlFilteringInterstitialEvent(expected_event); + } else { + validator.ExpectURLFilteringInterstitialEventWithReferrers(expected_event); + } safe_browsing::RTLookupResponse response; auto* threat_info = response.add_threat_info();
diff --git a/chrome/browser/extensions/extension_fullscreen_apitest.cc b/chrome/browser/extensions/extension_fullscreen_apitest.cc index b19e1d6..11e36580 100644 --- a/chrome/browser/extensions/extension_fullscreen_apitest.cc +++ b/chrome/browser/extensions/extension_fullscreen_apitest.cc
@@ -5,6 +5,7 @@ #include "build/build_config.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "content/public/test/browser_test.h" @@ -45,10 +46,14 @@ #endif IN_PROC_BROWSER_TEST_F(ExtensionApiTest, MAYBE_FocusWindowDoesNotExitFullscreen) { - browser()->exclusive_access_manager()->context()->EnterFullscreen( - url::Origin(), - EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - display::kInvalidDisplayId); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->EnterFullscreen( + url::Origin(), + EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, + display::kInvalidDisplayId); ASSERT_TRUE(browser()->window()->IsFullscreen()); ASSERT_TRUE(RunExtensionTest("window_update/focus")) << message_; ASSERT_TRUE(browser()->window()->IsFullscreen()); @@ -57,10 +62,14 @@ // Fails flakily: crbug.com/335640705. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, DISABLED_UpdateWindowSizeExitsFullscreen) { - browser()->exclusive_access_manager()->context()->EnterFullscreen( - url::Origin(), - EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - display::kInvalidDisplayId); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->EnterFullscreen( + url::Origin(), + EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, + display::kInvalidDisplayId); ASSERT_TRUE(RunExtensionTest("window_update/sizing")) << message_; ASSERT_FALSE(browser()->window()->IsFullscreen()); }
diff --git a/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc b/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc index 28ff3c8..e65db98 100644 --- a/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc +++ b/chrome/browser/extensions/keyed_services/chrome_browser_context_keyed_service_factories.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/extensions/error_console/error_console_factory.h" #include "chrome/browser/extensions/extension_action_dispatcher.h" #include "chrome/browser/extensions/extension_allowlist_factory.h" +#include "chrome/browser/extensions/extension_error_controller_factory.h" #include "chrome/browser/extensions/extension_garbage_collector_factory.h" #include "chrome/browser/extensions/extension_gcm_app_handler.h" #include "chrome/browser/extensions/extension_management.h" @@ -29,14 +30,13 @@ #include "chrome/browser/extensions/install_tracker_factory.h" #include "chrome/browser/extensions/install_verifier_factory.h" #include "chrome/browser/extensions/manifest_v2_experiment_manager.h" +#include "chrome/browser/extensions/menu_manager_factory.h" #include "chrome/browser/extensions/permissions/permissions_updater.h" #include "chrome/browser/extensions/shared_module_service_factory.h" #include "chrome/browser/extensions/updater/extension_updater_factory.h" #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "chrome/browser/extensions/extension_error_controller_factory.h" #include "chrome/browser/extensions/extension_web_ui_override_registrar.h" -#include "chrome/browser/extensions/menu_manager_factory.h" #include "chrome/browser/extensions/permissions/permissions_updater.h" #include "chrome/browser/extensions/plugin_manager.h" #include "chrome/browser/extensions/warning_badge_service_factory.h" @@ -67,6 +67,7 @@ extensions::ErrorConsoleFactory::GetInstance(); extensions::ExtensionActionDispatcher::GetFactoryInstance(); extensions::ExtensionAllowlistFactory::GetInstance(); + extensions::ExtensionErrorControllerFactory::GetInstance(); extensions::ExtensionGarbageCollectorFactory::GetInstance(); extensions::ExtensionGCMAppHandler::GetFactoryInstance(); extensions::ExtensionManagementFactory::GetInstance(); @@ -78,12 +79,11 @@ extensions::InstallTrackerFactory::GetInstance(); extensions::InstallVerifierFactory::GetInstance(); extensions::ManifestV2ExperimentManager::GetFactory(); + extensions::MenuManagerFactory::GetInstance(); extensions::PermissionsUpdater::EnsureAssociatedFactoryBuilt(); extensions::SharedModuleServiceFactory::GetInstance(); #if BUILDFLAG(ENABLE_EXTENSIONS) - extensions::ExtensionErrorControllerFactory::GetInstance(); - extensions::MenuManagerFactory::GetInstance(); #if BUILDFLAG(ENABLE_PLUGINS) extensions::PluginManager::GetFactoryInstance(); #endif // BUILDFLAG(ENABLE_PLUGINS)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 49afe15..c474b56 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -7373,6 +7373,11 @@ "expiry_milestone": 150 }, { + "name": "omnibox-mobile-parity-update-v2", + "owners": [ "ender@google.com", "hanxi@google.com", "pnoland@google.com", "chrome-mobile-search@google.com", "clank-start@google.com"], + "expiry_milestone": 150 + }, + { "name": "omnibox-most-visited-tiles-horizontal-render-group", "owners": [ "stkhapugin@chromium.org", "chrome-mobile-search@google.com"], "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 38f44ab..a7d53f10 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2945,6 +2945,12 @@ "When set, applies certain assets to match Desktop visuals and " "descriptions"; +const char kOmniboxMobileParityUpdateV2Name[] = + "Omnibox Mobile parity update V2"; +const char kOmniboxMobileParityUpdateV2Description[] = + "When set, applies certain assets to match Desktop visuals and " + "descriptions, version V2"; + const char kOmniboxNumNtpZpsRecentSearchesName[] = "Omnibox: Recent Searches on new tab page ZPS"; const char kOmniboxNumNtpZpsRecentSearchesDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index e7baf99..717e0f8 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1727,6 +1727,9 @@ extern const char kOmniboxMobileParityUpdateName[]; extern const char kOmniboxMobileParityUpdateDescription[]; +extern const char kOmniboxMobileParityUpdateV2Name[]; +extern const char kOmniboxMobileParityUpdateV2Description[]; + extern const char kOmniboxNumNtpZpsRecentSearchesName[]; extern const char kOmniboxNumNtpZpsRecentSearchesDescription[];
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index e55a2c7b..1b064077 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -685,7 +685,10 @@ public static final CachedFlag sAndroidMinimalUiLargeScreen = newCachedFlag(ANDROID_MINIMAL_UI_LARGE_SCREEN, false, true); public static final CachedFlag sAndroidProgressBarVisualUpdate = - newCachedFlag(ANDROID_PROGRESS_BAR_VISUAL_UPDATE, false); + newCachedFlag( + ANDROID_PROGRESS_BAR_VISUAL_UPDATE, + /* defaultValue= */ false, + /* defaultValueInTests= */ true); public static final CachedFlag sAndroidSurfaceColorUpdate = newCachedFlag( ANDROID_SURFACE_COLOR_UPDATE,
diff --git a/chrome/browser/gesturenav/android/java/src/org/chromium/chrome/browser/gesturenav/HardwareDraw.java b/chrome/browser/gesturenav/android/java/src/org/chromium/chrome/browser/gesturenav/HardwareDraw.java index 141ba578..c5fedb7 100644 --- a/chrome/browser/gesturenav/android/java/src/org/chromium/chrome/browser/gesturenav/HardwareDraw.java +++ b/chrome/browser/gesturenav/android/java/src/org/chromium/chrome/browser/gesturenav/HardwareDraw.java
@@ -14,14 +14,11 @@ import android.graphics.RenderNode; import android.media.Image; import android.media.ImageReader; -import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.view.Surface; import android.view.View; -import androidx.annotation.RequiresApi; - import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.base.TraceEvent; @@ -39,9 +36,8 @@ /** * Uses a {@link RenderNode} to perform bitmap capture of a java View. This walks the View hierarchy * synchronously, populating a list of instructions. Then, on a separate thread,the instructions are - * executed to paint colors onto a {@link Bitmap}. Uses functionality that requires Android Q+. + * executed to paint colors onto a {@link Bitmap}. */ -@RequiresApi(Build.VERSION_CODES.Q) @NullMarked public class HardwareDraw { @@ -52,10 +48,7 @@ * consumer. On the thread pool, the Renderer requests and blocks waiting the producer to * produce a frame, but the producer itself runs on a hidden Android render thread. The consumer * part of the Renderer runs on a dedicated thread. - * - * <p>RenderNode was added in API level 29 (Android 10). So restrict Renderer as well. */ - @RequiresApi(Build.VERSION_CODES.Q) private static class Renderer implements ImageReader.OnImageAvailableListener { private final ThreadUtils.ThreadChecker mUiThreadChecker;
diff --git a/chrome/browser/glic/browser_ui/glic_border_view.cc b/chrome/browser/glic/browser_ui/glic_border_view.cc index 7a363510..ef8630c 100644 --- a/chrome/browser/glic/browser_ui/glic_border_view.cc +++ b/chrome/browser/glic/browser_ui/glic_border_view.cc
@@ -23,6 +23,7 @@ #include "chrome/common/chrome_features.h" #include "content/public/browser/context_factory.h" #include "content/public/browser/gpu_data_manager.h" +#include "content/public/common/color_parser.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/compositor/compositor.h" #include "ui/compositor/layer.h" @@ -84,6 +85,37 @@ } return insets_for_contents_border; } + +std::vector<SkColor> GetParameterizedColors() { + std::vector<SkColor> colors; + if (base::FeatureList::IsEnabled(features::kGlicParameterizedShader)) { + std::vector<std::string> unparsed_colors = + base::SplitString(::features::kGlicParameterizedShaderColors.Get(), "#", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const auto& unparsed : unparsed_colors) { + SkColor result; + CHECK(content::ParseHexColorString("#" + unparsed, &result)); + colors.push_back(result); + } + } + return colors; +} + +std::vector<float> GetParameterizedFloats() { + std::vector<float> floats; + if (base::FeatureList::IsEnabled(features::kGlicParameterizedShader)) { + std::vector<std::string> unparsed_floats = + base::SplitString(::features::kGlicParameterizedShaderFloats.Get(), "#", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + for (const auto& unparsed : unparsed_floats) { + double result; + CHECK(base::StringToDouble(unparsed, &result)); + floats.push_back(static_cast<float>(result)); + } + } + return floats; +} + } // namespace GlicBorderView::Factory* GlicBorderView::Factory::factory_ = nullptr; @@ -298,6 +330,8 @@ : updater_(std::make_unique<BorderViewUpdater>(browser, this)), creation_time_(base::TimeTicks::Now()), tester_(std::move(tester)), + colors_(GetParameterizedColors()), + floats_(GetParameterizedFloats()), theme_service_(ThemeServiceFactory::GetForProfile(browser->GetProfile())), browser_(browser) { auto* gpu_data_manager = content::GpuDataManager::GetInstance(); @@ -308,12 +342,7 @@ // will observe GPU changes to keep hardware acceleration status updated. gpu_data_manager_observer_.Observe(gpu_data_manager); - shader_ = - ForceSimplifiedShader() - ? ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_GLIC_SIMPLIFIED_BORDER_SHADER) - : ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_GLIC_BORDER_SHADER); + UpdateShader(); CHECK(!shader_.empty()) << "Shader not initialized."; auto* glic_service = @@ -374,12 +403,31 @@ {.name = SkString("u_dark"), .value = UseDarkMode(theme_service_) ? 1 : 0}}; + std::vector<cc::PaintShader::Float4Uniform> float4_uniforms; + if (base::FeatureList::IsEnabled(features::kGlicParameterizedShader)) { + for (int i = 0; i < static_cast<int>(colors_.size()); ++i) { + float4_uniforms.push_back( + {.name = SkString(absl::StrFormat("u_color%d", i + 1)), + .value = + SkV4{static_cast<float>(SkColorGetR(colors_[i]) / 255.0), + static_cast<float>(SkColorGetG(colors_[i]) / 255.0), + static_cast<float>(SkColorGetB(colors_[i]) / 255.0), 1.f}}); + } + for (int i = 0; i < static_cast<int>(floats_.size()); ++i) { + float_uniforms.push_back( + {.name = SkString(absl::StrFormat("u_float%d", i + 1)), + .value = floats_[i]}); + } + } + views::View::OnPaint(canvas); cc::PaintFlags flags; auto shader = cc::PaintShader::MakeSkSLCommand( shader_, std::move(float_uniforms), std::move(float2_uniforms), - /*float4_uniforms=*/{}, std::move(int_uniforms), cached_paint_shader_); + std::move(float4_uniforms), std::move(int_uniforms), + cached_paint_shader_); + flags.setShader(shader); if (base::FeatureList::IsEnabled(features::kGlicUseShaderCache)) { @@ -506,12 +554,7 @@ if (has_hardware_acceleration_ != has_hardware_acceleration) { has_hardware_acceleration_ = has_hardware_acceleration; - shader_ = - ForceSimplifiedShader() - ? ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_GLIC_SIMPLIFIED_BORDER_SHADER) - : ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_GLIC_BORDER_SHADER); + UpdateShader(); if (IsShowing()) { SchedulePaint(); @@ -734,6 +777,24 @@ return service; } +void GlicBorderView::UpdateShader() { + if (base::FeatureList::IsEnabled(features::kGlicParameterizedShader)) { + shader_ = + ForceSimplifiedShader() + ? ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_GLIC_SIMPLIFIED_PARAMETERIZED_BORDER_SHADER) + : ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_GLIC_PARAMETERIZED_BORDER_SHADER); + } else { + shader_ = + ForceSimplifiedShader() + ? ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_GLIC_SIMPLIFIED_BORDER_SHADER) + : ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_GLIC_BORDER_SHADER); + } +} + BEGIN_METADATA(GlicBorderView) END_METADATA
diff --git a/chrome/browser/glic/browser_ui/glic_border_view.h b/chrome/browser/glic/browser_ui/glic_border_view.h index e702325..3f31f7160 100644 --- a/chrome/browser/glic/browser_ui/glic_border_view.h +++ b/chrome/browser/glic/browser_ui/glic_border_view.h
@@ -131,6 +131,8 @@ GlicKeyedService* GetGlicService() const; + void UpdateShader(); + // A utility class that subscribe to `GlicKeyedService` for various browser UI // status change. class BorderViewUpdater; @@ -175,6 +177,9 @@ sk_sp<cc::PaintShader> cached_paint_shader_; + const std::vector<SkColor> colors_; + const std::vector<float> floats_; + raw_ptr<ui::Compositor> compositor_ = nullptr; raw_ptr<ThemeService> theme_service_ = nullptr; raw_ptr<Browser> browser_ = nullptr;
diff --git a/chrome/browser/glic/resources/browser_resources.grd b/chrome/browser/glic/resources/browser_resources.grd index 18c49eb..3f0f102 100644 --- a/chrome/browser/glic/resources/browser_resources.grd +++ b/chrome/browser/glic/resources/browser_resources.grd
@@ -17,7 +17,9 @@ <includes> <include name="IDR_GLIC_ATTACH_BUTTON_VECTOR_ICON" file="glic_attach_button.icon" type="BINDATA" compress="brotli" /> <include name="IDR_GLIC_BORDER_SHADER" file="border.sksl" type="BINDATA" compress="brotli" /> + <include name="IDR_GLIC_PARAMETERIZED_BORDER_SHADER" file="border.sksl" type="BINDATA" compress="brotli" /> <include name="IDR_GLIC_SIMPLIFIED_BORDER_SHADER" file="border.sksl" type="BINDATA" compress="brotli" /> + <include name="IDR_GLIC_SIMPLIFIED_PARAMETERIZED_BORDER_SHADER" file="border.sksl" type="BINDATA" compress="brotli" /> <include name="IDR_GLIC_BUTTON_VECTOR_ICON" file="glic_button.icon" type="BINDATA" compress="brotli" /> <include name="IDR_GLIC_STATUS_ICON" file="glic_button.icon" type="BINDATA" compress="brotli" /> <include name="IDR_GLIC_LOGO" file="logo.svg" type="BINDATA" compress="brotli" /> @@ -252,18 +254,27 @@ <message name="IDS_SETTINGS_GLIC_PERMISSIONS_LOCATION_TOGGLE_SUBLABEL" translateable="false" desc="Sublabel describing the 'enable location sharing' setting."> Use your location to allow enhanced accuracy </message> + <message name="IDS_SETTINGS_GLIC_PERMISSIONS_LOCATION_TOGGLE_SUBLABEL_DATA_PROTECTED" translateable="false" desc="Sublabel describing the 'enable location sharing' setting (data protected)."> + Use your location to allow enhanced accuracy but not for model improvement + </message> <message name="IDS_SETTINGS_GLIC_PERMISSIONS_MICROPHONE_TOGGLE" translateable="false" desc="Name of the 'enable microphone' setting."> Microphone </message> <message name="IDS_SETTINGS_GLIC_PERMISSIONS_MICROPHONE_TOGGLE_SUBLABEL" translateable="false" desc="Sublabel describing the 'enable microphone' setting."> Enable use of your microphone </message> + <message name="IDS_SETTINGS_GLIC_PERMISSIONS_MICROPHONE_TOGGLE_SUBLABEL_DATA_PROTECTED" translateable="false" desc="Sublabel describing the 'enable microphone' setting (data protected)."> + Enable use of your microphone but not for model improvement + </message> <message name="IDS_SETTINGS_GLIC_PERMISSIONS_TAB_ACCESS_TOGGLE" translateable="false" desc="Name of the 'enable tab access' setting."> Current tab access </message> <message name="IDS_SETTINGS_GLIC_PERMISSIONS_TAB_ACCESS_TOGGLE_SUBLABEL" translateable="false" desc="Sublabel describing the 'tab access' setting."> Allow feature </message> + <message name="IDS_SETTINGS_GLIC_PERMISSIONS_TAB_ACCESS_TOGGLE_SUBLABEL_DATA_PROTECTED" translateable="false" desc="Sublabel describing the 'tab access' setting (data protected)."> + Allow feature but not for model improvement + </message> <message name="IDS_SETTINGS_GLIC_PERMISSIONS_ACTIVITY_BUTTON" translateable="false" desc="Name of the 'activity' button."> Activity </message>
diff --git a/chrome/browser/glic/resources/internal b/chrome/browser/glic/resources/internal index 4754412..c423a15 160000 --- a/chrome/browser/glic/resources/internal +++ b/chrome/browser/glic/resources/internal
@@ -1 +1 @@ -Subproject commit 475441278dca99489f0e148f278ca395fd07926d +Subproject commit c423a1559c0be8f0c1748dcdb0971ce13bf5dbcd
diff --git a/chrome/browser/gpu/chrome_browser_main_extra_parts_gpu.cc b/chrome/browser/gpu/chrome_browser_main_extra_parts_gpu.cc index 465c8aa..c238075 100644 --- a/chrome/browser/gpu/chrome_browser_main_extra_parts_gpu.cc +++ b/chrome/browser/gpu/chrome_browser_main_extra_parts_gpu.cc
@@ -11,7 +11,8 @@ #include "gpu/config/gpu_preferences.h" namespace { -const char kTrialName[] = "SkiaBackend"; +const char kSkiaTrialName[] = "SkiaBackend"; +const char kEGLTrialName[] = "EGLDisplayType"; // Synthetic trial group names. Groups added here should be added to finch // service side as well. @@ -47,9 +48,17 @@ void ChromeBrowserMainExtraPartsGpu::OnGpuInfoUpdate() { const auto* backend_name = GetSkiaBackendName(); if (backend_name) { - ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(kTrialName, + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(kSkiaTrialName, backend_name); } + auto* manager = content::GpuDataManager::GetInstance(); + if (manager->IsEssentialGpuInfoAvailable()) { + const std::string& display_type = manager->GetGPUInfo().display_type; + if (!display_type.empty()) { + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(kEGLTrialName, + display_type); + } + } } const char* ChromeBrowserMainExtraPartsGpu::GetSkiaBackendName() const {
diff --git a/chrome/browser/net/private_network_access_browsertest.cc b/chrome/browser/net/private_network_access_browsertest.cc index 5c14b99..5fe39d9 100644 --- a/chrome/browser/net/private_network_access_browsertest.cc +++ b/chrome/browser/net/private_network_access_browsertest.cc
@@ -147,26 +147,26 @@ std::vector<WebFeature> AllAddressSpaceFeatures() { return { - WebFeature::kAddressSpacePrivateSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePrivateNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLocal, - WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicSecureContextEmbeddedPrivate, - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedPrivate, - WebFeature::kAddressSpaceUnknownSecureContextEmbeddedPrivate, - WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedPrivate, - WebFeature::kAddressSpacePrivateSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePrivateNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLocal, - WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicSecureContextNavigatedToPrivate, - WebFeature::kAddressSpacePublicNonSecureContextNavigatedToPrivate, - WebFeature::kAddressSpaceUnknownSecureContextNavigatedToPrivate, - WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToPrivate, + WebFeature::kAddressSpaceLocalSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceLocalSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceLocalNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLocalV2, WebFeature::kPrivateNetworkAccessFetchedWorkerScript, WebFeature::kPrivateNetworkAccessFetchedSubFrame, WebFeature::kPrivateNetworkAccessFetchedTopFrame, @@ -380,7 +380,7 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, 1}, })); } @@ -423,7 +423,8 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + 1}, {WebFeature::kPrivateNetworkAccessFetchedTopFrame, 1}, })); } @@ -455,7 +456,8 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + 1}, {WebFeature::kPrivateNetworkAccessFetchedTopFrame, 1}, })); } @@ -515,7 +517,8 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + 1}, {WebFeature::kPrivateNetworkAccessFetchedSubFrame, 1}, })); } @@ -557,7 +560,8 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + 1}, {WebFeature::kPrivateNetworkAccessFetchedSubFrame, 1}, })); } @@ -589,7 +593,8 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, 1}, + {WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + 1}, {WebFeature::kPrivateNetworkAccessFetchedSubFrame, 1}, })); } @@ -781,7 +786,7 @@ feature_histogram_tester.ExpectCounts(AddFeatureCounts( AllZeroFeatureCounts(AllAddressSpaceFeatures()), { - {WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, 1}, + {WebFeature::kAddressSpacePublicSecureContextEmbeddedLocalV2, 1}, })); }
diff --git a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java index 57f59b3..2d7b38ca 100644 --- a/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java +++ b/chrome/browser/notifications/android/java/src/org/chromium/chrome/browser/notifications/NotificationUmaTracker.java
@@ -8,7 +8,6 @@ import android.text.format.DateUtils; import androidx.annotation.IntDef; -import androidx.annotation.RequiresApi; import androidx.core.app.NotificationManagerCompat; import org.chromium.base.Callback; @@ -711,7 +710,6 @@ }); } - @RequiresApi(26) private void isChannelBlocked( @ChromeChannelDefinitions.ChannelId String channelId, Callback<Boolean> callback) { mNotificationManager.getNotificationChannel(
diff --git a/chrome/browser/notifications/platform_notification_service_impl.cc b/chrome/browser/notifications/platform_notification_service_impl.cc index 5660825..1f19979 100644 --- a/chrome/browser/notifications/platform_notification_service_impl.cc +++ b/chrome/browser/notifications/platform_notification_service_impl.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/permissions/notifications_engagement_service_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/safety_hub/disruptive_notification_permissions_manager.h" @@ -141,7 +142,10 @@ // (b) the browser is fullscreen // (c) the browser has focus. if (active_contents->GetURL().DeprecatedGetOriginAsURL() == origin && - browser->exclusive_access_manager()->context()->IsFullscreen() && + browser->GetFeatures() + .exclusive_access_manager() + ->context() + ->IsFullscreen() && browser->window()->IsActive()) { return true; }
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index a2bf5fe4..af18405f 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -33,6 +33,7 @@ #include "chrome/browser/permissions/permission_manager_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -966,9 +967,15 @@ // Set the other browser fullscreen ui_test_utils::ToggleFullscreenModeAndWait(other_browser); - ASSERT_TRUE(browser()->exclusive_access_manager()->context()->IsFullscreen()); - ASSERT_TRUE( - other_browser->exclusive_access_manager()->context()->IsFullscreen()); + ASSERT_TRUE(browser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->IsFullscreen()); + ASSERT_TRUE(other_browser->GetFeatures() + .exclusive_access_manager() + ->context() + ->IsFullscreen()); ui_test_utils::BrowserActivationWaiter(other_browser).WaitForActivation(); ASSERT_FALSE(browser()->window()->IsActive());
diff --git a/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc b/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc index ae5e283..8bfd068b 100644 --- a/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc +++ b/chrome/browser/optimization_guide/hints_fetcher_browsertest.cc
@@ -306,8 +306,9 @@ // Acquire the |lock_| inside to avoid starving other consumers of the // lock. base::AutoLock lock(lock_); - if (count_hints_requests_received_ > 0) + if (count_hints_requests_received_ > 0) { return; + } } base::RunLoop run_loop; @@ -402,8 +403,9 @@ static_cast<size_t>(hints_request.hosts().size())); // Only verify the hints if there are hosts in the request. - if (!hints_request.hosts().empty()) + if (!hints_request.hosts().empty()) { VerifyHintsMatchExpectedHostsAndUrls(hints_request); + } if (response_type_ == optimization_guide::HintsFetcherRemoteResponseType::kSuccessful) { @@ -448,8 +450,9 @@ // hosts in not matched. void VerifyHintsMatchExpectedHostsAndUrls( const optimization_guide::proto::GetHintsRequest& hints_request) const { - if (!expect_hints_request_for_hosts_and_urls_) + if (!expect_hints_request_for_hosts_and_urls_) { return; + } base::flat_set<std::string> hosts_and_urls_requested; for (const auto& host : hints_request.hosts()) { @@ -1810,6 +1813,7 @@ optimization_guide::FetcherRequestStatus::kSuccess, 1); } +// TODO(crbug.com/425936619): Add checks for url, hint counts, context. class ProactivePersonalizationHintsFetcherBrowserTest : public HintsFetcherBrowserTest { public: @@ -1905,6 +1909,36 @@ 1); } +// Verify access token is attached during url fetching if a +// personalizable optimization type is requested. +// TODO(crbug.com/40919396): De-leakify and re-enable. +#if BUILDFLAG(IS_LINUX) && defined(LEAK_SANITIZER) +#define MAYBE_FetchingUrlFetchesWithAccessToken \ + DISABLED_FetchingUrlFetchesWithAccessToken +#else +#define MAYBE_FetchingUrlFetchesWithAccessToken \ + FetchingUrlFetchesWithAccessToken +#endif +IN_PROC_BROWSER_TEST_F(ProactivePersonalizationHintsFetcherBrowserTest, + MAYBE_FetchingUrlFetchesWithAccessToken) { + const base::HistogramTester* histogram_tester = GetHistogramTester(); + + EnableSignin(); + SetExpectedBearerAccessToken("Bearer access_token"); + + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), search_results_page_url())); + + WaitUntilHintsFetcherRequestReceived(); + + EXPECT_GE(optimization_guide::RetryForHistogramUntilCountReached( + histogram_tester, + "OptimizationGuide.HintsFetcher.GetHintsRequest.RequestStatus." + "BatchUpdateGoogleSRP", + 1), + 1); +} + class ProactivePersonalizationNoAllowedTypesHintsFetcherBrowserTest : public ProactivePersonalizationHintsFetcherBrowserTest { public: @@ -1956,3 +1990,34 @@ 1), 1); } + +// Verify access token is not attached during url fetching if no personalizable +// optimization type is requested. +// TODO(crbug.com/40919396): De-leakify and re-enable. +#if BUILDFLAG(IS_LINUX) && defined(LEAK_SANITIZER) +#define MAYBE_FetchingUrlDoesNotFetchWithAccessToken \ + DISABLED_FetchingUrlDoesNotFetchWithAccessToken +#else +#define MAYBE_FetchingUrlDoesNotFetchWithAccessToken \ + FetchingUrlDoesNotFetchWithAccessToken +#endif +IN_PROC_BROWSER_TEST_F( + ProactivePersonalizationNoAllowedTypesHintsFetcherBrowserTest, + MAYBE_FetchingUrlDoesNotFetchWithAccessToken) { + const base::HistogramTester* histogram_tester = GetHistogramTester(); + + EnableSignin(); + SetExpectedBearerAccessToken(std::string()); + + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), search_results_page_url())); + + WaitUntilHintsFetcherRequestReceived(); + + EXPECT_GE(optimization_guide::RetryForHistogramUntilCountReached( + histogram_tester, + "OptimizationGuide.HintsFetcher.GetHintsRequest.RequestStatus." + "BatchUpdateGoogleSRP", + 1), + 1); +}
diff --git a/chrome/browser/password_manager/password_manager_settings_service_factory.cc b/chrome/browser/password_manager/password_manager_settings_service_factory.cc index 53a5217..d44e137 100644 --- a/chrome/browser/password_manager/password_manager_settings_service_factory.cc +++ b/chrome/browser/password_manager/password_manager_settings_service_factory.cc
@@ -16,6 +16,8 @@ #include "chrome/browser/password_manager/android/password_manager_settings_service_android_impl.h" #include "chrome/browser/password_manager/android/password_manager_settings_service_android_migration_impl.h" #include "chrome/browser/password_manager/android/password_manager_util_bridge.h" +#include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h" +#include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" #endif @@ -77,8 +79,13 @@ profile->GetPrefs(), std::make_unique< password_manager_android_util::PasswordManagerUtilBridge>())) { - return std::make_unique<PasswordManagerSettingsServiceAndroidImpl>( - profile->GetPrefs(), SyncServiceFactory::GetForProfile(profile)); + auto service = + std::make_unique<PasswordManagerSettingsServiceAndroidImpl>( + profile->GetPrefs(), SyncServiceFactory::GetForProfile(profile)); + FederatedIdentityAutoReauthnPermissionContextFactory::GetForProfile( + profile) + ->OnPasswordManagerSettingsServiceInitialized(service.get()); + return service; } return nullptr; }
diff --git a/chrome/browser/platform_util_ash.cc b/chrome/browser/platform_util_ash.cc index 6bcc20e..1bd733e 100644 --- a/chrome/browser/platform_util_ash.cc +++ b/chrome/browser/platform_util_ash.cc
@@ -3,8 +3,11 @@ // found in the LICENSE file. #include "ash/wm/window_pin_util.h" +#include "base/containers/to_vector.h" #include "base/files/file_path.h" #include "base/functional/bind.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/file_manager/open_util.h" #include "chrome/browser/ash/guest_os/guest_os_external_protocol_handler.h" #include "chrome/browser/platform_util.h" @@ -13,6 +16,8 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/simple_message_box.h" +#include "chrome/browser/web_applications/app_service/publisher_helper.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "content/public/browser/browser_thread.h" #include "ui/aura/window.h" @@ -62,6 +67,23 @@ path.BaseName().AsUTF16Unsafe(), l10n_util::GetStringUTF16(message_id)); } +void HandleWebAppManifestProtocolHandler( + Profile* profile, + const GURL& url, + const std::vector<std::string>& app_ids) { + CHECK(!app_ids.empty()); + // TODO(crbug.com/422422887): Figure out how to disambiguate conflicting + // protocol handlers; for now, pick the first one in the list. + const auto& app_id = app_ids[0]; + apps::AppLaunchParams params(app_id, + apps::LaunchContainer::kLaunchContainerWindow, + WindowOpenDisposition::NEW_FOREGROUND_TAB, + apps::LaunchSource::kFromProtocolHandler); + params.protocol_handler_launch_url = url; + apps::AppServiceProxyFactory::GetForProfile(profile)->LaunchAppWithParams( + std::move(params)); +} + } // namespace namespace internal { @@ -102,6 +124,13 @@ // ChromeContentBrowserClient::HandleExternalProtocol. DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (std::vector<std::string> app_ids = + web_app::GetWebAppIdsForProtocolUrl(profile, url); + !app_ids.empty()) { + HandleWebAppManifestProtocolHandler(profile, url, app_ids); + return; + } + std::optional<guest_os::GuestOsUrlHandler> handler = guest_os::GuestOsUrlHandler::GetForUrl(profile, url); if (handler) {
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java index cd013d89..a53ca66 100644 --- a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java +++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsTest.java
@@ -23,8 +23,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.os.Build; - import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.test.filters.MediumTest; @@ -44,7 +42,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; @@ -108,10 +105,6 @@ @Test @MediumTest - @DisableIf.Build( - supported_abis_includes = "armeabi-v7a", - sdk_is_less_than = Build.VERSION_CODES.O, - message = "Flaky only on test-n-phone, crbug.com/1469008") public void testRestoreTabsPromo_triggerBottomSheetView() { // Setup mock data ForeignSessionTab tab = new ForeignSessionTab(JUnitTestGURLs.URL_1, "title", 32L, 32L, 0);
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 1340d8b0..335ac75 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1457,8 +1457,9 @@ return false; } - FullscreenController* controller = - browser->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* controller = browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); return controller->IsTabFullscreen(); } @@ -1468,8 +1469,9 @@ return false; } - KeyboardLockController* controller = - browser->exclusive_access_manager()->keyboard_lock_controller(); + KeyboardLockController* controller = browser->GetFeatures() + .exclusive_access_manager() + ->keyboard_lock_controller(); return controller->RequiresPressAndHoldEscToExit(); } @@ -2163,7 +2165,8 @@ } // Only show item if in fullscreen mode. - if (!browser->exclusive_access_manager() + if (!browser->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsControllerInitiatedFullscreen()) { return; @@ -4210,7 +4213,7 @@ NOTREACHED(); } - browser->exclusive_access_manager()->ExitExclusiveAccess(); + browser->GetFeatures().exclusive_access_manager()->ExitExclusiveAccess(); } void RenderViewContextMenu::ExecCopyLinkText() {
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index ddc43ac..e879e2f 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -2688,9 +2688,10 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - // Permits sharing the page screenshot by default. + // Permits sharing the page screenshot and content by default. PrefService* prefs = browser()->profile()->GetPrefs(); prefs->SetBoolean(lens::prefs::kLensSharingPageScreenshotEnabled, true); + prefs->SetBoolean(lens::prefs::kLensSharingPageContentEnabled, true); } void TearDownOnMainThread() override { @@ -2880,8 +2881,10 @@ ASSERT_TRUE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_ROTATECCW)); // Set to tab fullscreen, and test that 'Rotate' items are disabled. - FullscreenController* fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); fullscreen_controller->set_is_tab_fullscreen_for_testing(true); ASSERT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_ROTATECW));
diff --git a/chrome/browser/resources/lens/overlay/lens_overlay_app.html b/chrome/browser/resources/lens/overlay/lens_overlay_app.html index 5f68114..e8e9f394 100644 --- a/chrome/browser/resources/lens/overlay/lens_overlay_app.html +++ b/chrome/browser/resources/lens/overlay/lens_overlay_app.html
@@ -325,6 +325,9 @@ --cr-searchbox-height: 48px; --cr-searchbox-icon-size-in-searchbox: 28px; --cr-searchbox-icon-top-position: 0px; + /* Colors for searchbox ghost loader */ + --color-searchbox-ghost-loader-loading-bar-1: #F1F3F4; + --color-searchbox-ghost-loader-loading-bar-2: #ECEDEF; position: absolute; inset-block-start: 40px; inset-inline-end: 140px;
diff --git a/chrome/browser/resources/lens/shared/searchbox_ghost_loader.html b/chrome/browser/resources/lens/shared/searchbox_ghost_loader.html index ee4ba605..92d8f83 100644 --- a/chrome/browser/resources/lens/shared/searchbox_ghost_loader.html +++ b/chrome/browser/resources/lens/shared/searchbox_ghost_loader.html
@@ -137,6 +137,8 @@ .loading-bar { animation: 2s fadeInOut calc(0.1s * var(--loading-bar-animation-delay)) infinite; + /* The initial background color of the loading bar before the fade in/out animation starts. */ + background-color: var(--color-searchbox-ghost-loader-loading-bar-1); border-radius: 4px; height: 20px; width: 100%;
diff --git a/chrome/browser/resources/new_tab_footer/app.ts b/chrome/browser/resources/new_tab_footer/app.ts index c6c7262a..5f40378 100644 --- a/chrome/browser/resources/new_tab_footer/app.ts +++ b/chrome/browser/resources/new_tab_footer/app.ts
@@ -52,7 +52,8 @@ EXTENSION_NAME = 2, MANAGEMENT_NOTICE = 3, BACKGROUND_ATTRIBUTION = 4, - MAX_VALUE = BACKGROUND_ATTRIBUTION, + CONTEXT_MENU = 5, + MAX_VALUE = CONTEXT_MENU, } const CUSTOMIZE_URL_PARAM: string = 'customize'; @@ -234,6 +235,7 @@ protected onContextMenu_(e: MouseEvent) { this.handler_.showContextMenu({x: e.clientX, y: e.clientY}); + recordClick(FooterElement.CONTEXT_MENU); } protected onExtensionNameClick_(e: Event) {
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.html b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.html index f718dc0d..e0d9be4 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.html +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.html
@@ -104,7 +104,9 @@ <template is="dom-repeat" items="[[expandedBrowsingDataTypeOptionsList_]]"> <settings-checkbox pref="[[item.pref]]" no-set-pref - sub-label="[[item.subLabel]]" disabled="[[isDeletionInProgress_]]"> + sub-label-html="[[item.subLabel]]" + disabled="[[isDeletionInProgress_]]" + on-sub-label-link-clicked="onCheckboxSubLabelLinkClick_"> <div class="checkbox-title">[[item.label]]</div> </settings-checkbox> </template> @@ -113,8 +115,9 @@ <template is="dom-repeat" items="[[moreBrowsingDataTypeOptionsList_]]"> <settings-checkbox pref="[[item.pref]]" no-set-pref - sub-label="[[item.subLabel]]" - disabled="[[isDeletionInProgress_]]"> + sub-label-html="[[item.subLabel]]" + disabled="[[isDeletionInProgress_]]" + on-sub-label-link-clicked="onCheckboxSubLabelLinkClick_"> <div class="checkbox-title">[[item.label]]</div> </settings-checkbox> </template>
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.ts index 04c44fd..40fd6fe 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.ts +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog_v2.ts
@@ -25,7 +25,7 @@ import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import type {CrLinkRowElement} from 'chrome://resources/cr_elements/cr_link_row/cr_link_row.js'; import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js'; import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -476,6 +476,16 @@ this.setFocusOutlineToVisible_(); }); } + + private onCheckboxSubLabelLinkClick_(e: CustomEvent<{id: string}>) { + // <if expr="not is_chromeos"> + if (e.detail.id === 'signOutLink') { + this.syncBrowserProxy_.signOut(/*delete_profile=*/ false); + return; + } + // </if> + assertNotReached(`Invalid sub-label link with id: ${e.detail.id}`); + } } declare global {
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.html b/chrome/browser/resources/settings/controls/settings_checkbox.html index f6b3d30..0eae591 100644 --- a/chrome/browser/resources/settings/controls/settings_checkbox.html +++ b/chrome/browser/resources/settings/controls/settings_checkbox.html
@@ -40,7 +40,8 @@ aria-label="[[label]]"> <div id="label">[[label]] <slot></slot></div> <div id="subLabel" class="cr-secondary-text"> - <div inner-h-t-m-l="[[sanitizeInnerHtml_(subLabelHtml)]]"></div> + <div inner-h-t-m-l="[[sanitizeInnerHtml_(subLabelHtml)]]" + on-click="onSubLabelClick_"></div> [[subLabel]] </div> </cr-checkbox>
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.ts b/chrome/browser/resources/settings/controls/settings_checkbox.ts index 2ad9b59..23d06d66 100644 --- a/chrome/browser/resources/settings/controls/settings_checkbox.ts +++ b/chrome/browser/resources/settings/controls/settings_checkbox.ts
@@ -45,7 +45,6 @@ subLabelHtml: { type: String, value: '', - observer: 'onSubLabelHtmlChanged_', }, }; } @@ -67,16 +66,6 @@ this.$.checkbox.ariaDescription = this.$.subLabel.textContent!; } - /** - * Don't let clicks on a link inside the secondary label reach the checkbox. - */ - private onSubLabelHtmlChanged_() { - const links = this.$.subLabel.querySelectorAll('a'); - links.forEach((link) => { - link.addEventListener('click', this.stopPropagation_.bind(this)); - }); - } - private stopPropagation_(event: Event) { event.stopPropagation(); } @@ -86,7 +75,25 @@ } private sanitizeInnerHtml_(rawString: string): TrustedHTML { - return sanitizeInnerHtml(rawString); + return sanitizeInnerHtml(rawString, { + attrs: [ + 'id', + 'aria-label', + ], + }); + } + + private onSubLabelClick_(e: Event) { + const target = e.target as HTMLElement; + if (target.tagName === 'A') { + this.dispatchEvent(new CustomEvent( + 'sub-label-link-clicked', + {bubbles: true, composed: true, detail: {id: target.id}})); + e.preventDefault(); + + // Don't let link click events from the sub-label reach the checkbox. + e.stopPropagation(); + } } }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc index f3962ae..44957655 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc
@@ -14,6 +14,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" +#include "base/path_service.h" #include "base/test/bind.h" #include "base/test/scoped_command_line.h" #include "base/test/scoped_feature_list.h" @@ -27,6 +28,7 @@ #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h" +#include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" #include "components/enterprise/common/proto/connectors.pb.h" #include "components/safe_browsing/core/common/features.h" @@ -310,6 +312,85 @@ EXPECT_EQ(scanning_result, BinaryUploadService::Result::UPLOAD_FAILURE); } +TEST_F(CloudBinaryUploadServiceTest, FailsForEncryptedFile) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature( + enterprise_connectors::kEnableEncryptedFileUpload); + BinaryUploadService::Result scanning_result; + enterprise_connectors::ContentAnalysisResponse scanning_response; + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + base::FilePath file_path; + EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &file_path)); + file_path = file_path.AppendASCII("safe_browsing") + .AppendASCII("download_protection") + .AppendASCII("encrypted.zip"); + + ExpectNetworkResponse(/*should_succeed=*/false, + enterprise_connectors::ContentAnalysisResponse()); + + std::unique_ptr<MockRequest> request = MakeRequest( + &scanning_result, &scanning_response, /*is_advanced_protection*/ false); + request->set_analysis_connector( + enterprise_connectors::AnalysisConnector::FILE_ATTACHED); + ON_CALL(*request, GetRequestData(_)) + .WillByDefault(Invoke( + [file_path](BinaryUploadService::Request::DataCallback callback) { + BinaryUploadService::Request::Data data; + data.path = file_path; + data.size = 4; // Must not be zero. + std::move(callback).Run(BinaryUploadService::Result::FILE_ENCRYPTED, + std::move(data)); + })); + UploadForDeepScanning(std::move(request)); + + content::RunAllTasksUntilIdle(); + + EXPECT_EQ(scanning_result, BinaryUploadService::Result::UPLOAD_FAILURE); +} + +TEST_F(CloudBinaryUploadServiceTest, PassesForEncryptedFileIfEnabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + enterprise_connectors::kEnableEncryptedFileUpload); + BinaryUploadService::Result scanning_result; + enterprise_connectors::ContentAnalysisResponse scanning_response; + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + + base::FilePath file_path; + EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &file_path)); + file_path = file_path.AppendASCII("safe_browsing") + .AppendASCII("download_protection") + .AppendASCII("encrypted.zip"); + ExpectNetworkResponse(/*should_succeed=*/true, + enterprise_connectors::ContentAnalysisResponse()); + + std::unique_ptr<MockRequest> request = MakeRequest( + &scanning_result, &scanning_response, /*is_advanced_protection*/ false); + request->set_analysis_connector( + enterprise_connectors::AnalysisConnector::FILE_ATTACHED); + ON_CALL(*request, GetRequestData(_)) + .WillByDefault(Invoke( + [file_path](BinaryUploadService::Request::DataCallback callback) { + BinaryUploadService::Request::Data data; + data.path = file_path; + data.size = 4; // Must not be zero. + std::move(callback).Run(BinaryUploadService::Result::FILE_ENCRYPTED, + std::move(data)); + })); + UploadForDeepScanning(std::move(request)); + + // TODO(crbug.com/418020892): Use BrowserTaskEnvironment::RunUntilIdle() + // instead. + content::RunAllTasksUntilIdle(); + + EXPECT_EQ(scanning_result, BinaryUploadService::Result::SUCCESS); +} + TEST_F(CloudBinaryUploadServiceTest, Succeeds) { BinaryUploadService::Result scanning_result; enterprise_connectors::ContentAnalysisResponse scanning_response;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc index d988dea..3ecd477 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.cc
@@ -296,9 +296,9 @@ } // If chrome is being told to upload the content but the content is too large - // or is encrypted, fail now. + // or is encrypted and encrypted file upload is not enabled, fail now. if (get_data_result_ == BinaryUploadService::Result::FILE_TOO_LARGE || - get_data_result_ == BinaryUploadService::Result::FILE_ENCRYPTED) { + (get_data_result_ == BinaryUploadService::Result::FILE_ENCRYPTED && !ShouldUploadEncryptedFile())) { Finish(net::ERR_FAILED, net::HTTP_BAD_REQUEST, std::move(response_body)); return; } @@ -307,6 +307,11 @@ SendContentSoon(headers->GetNormalizedHeader(kUploadUrlHeader).value()); } +bool ResumableUploadRequest::ShouldUploadEncryptedFile() { + return base::FeatureList::IsEnabled( + enterprise_connectors::kEnableEncryptedFileUpload) && + scan_type_ == ASYNC; +} void ResumableUploadRequest::SendContentSoon(const std::string& upload_url) { auto request = std::make_unique<network::ResourceRequest>(); request->method = "POST";
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h index b34f8a8..2132141 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader.h
@@ -158,6 +158,10 @@ // This method also has the side effect of setting upload_url_. bool CanUploadContent(const scoped_refptr<net::HttpResponseHeaders>& headers); + // Returns true if `kEnableEncryptedFileUpload` + // feature is enabled and the `scan_type_` is ASYNC. + bool ShouldUploadEncryptedFile(); + // Helper used by metrics logging code. std::string GetRequestType();
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc index 459a2c0..590eee5a 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/resumable_uploader_unittest.cc
@@ -589,6 +589,59 @@ /*expected_bucket_count=*/1); } +TEST_P(ResumableUploadSendContentRequestTest, + HandlesEncryptedFileContentUploadIfEnabled) { + base::RunLoop run_loop; + base::RunLoop async_content_upload_run_loop; + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + enterprise_connectors::kEnableEncryptedFileUpload); + + auto verdict_callback = base::BindLambdaForTesting( + [&](bool success, int http_status, const std::string& response_data) { + run_loop.Quit(); + }); + + auto content_callback = + base::BindLambdaForTesting([&async_content_upload_run_loop]() { + async_content_upload_run_loop.Quit(); + }); + + auto mock_request = CreateRequest<MockResumableUploadRequest>( + BinaryUploadService::Result::FILE_ENCRYPTED, std::move(verdict_callback), + std::move(content_callback), false); + + test_url_loader_factory_.SetInterceptor( + base::BindLambdaForTesting([&](const network::ResourceRequest& request) { + if (request.url == GURL("https://google.com")) { + auto metadata_response_head = + network::CreateURLResponseHead(net::HTTP_OK); + metadata_response_head->headers->AddHeader("X-Goog-Upload-Status", + "active"); + metadata_response_head->headers->AddHeader("X-Goog-Upload-URL", + kUploadUrl); + test_url_loader_factory_.AddResponse( + GURL("https://google.com"), std::move(metadata_response_head), + "metadata_response", network::URLLoaderCompletionStatus(net::OK)); + } else if (request.url == GURL(kUploadUrl)) { + ASSERT_EQ(request.method, "POST"); + auto content_response_head = + network::CreateURLResponseHead(net::HTTP_OK); + content_response_head->headers->AddHeader("X-Goog-Upload-Status", + "final"); + test_url_loader_factory_.AddResponse( + GURL(kUploadUrl), std::move(content_response_head), + "final_response", network::URLLoaderCompletionStatus(net::OK)); + } else { + NOTREACHED(); + } + })); + mock_request->Start(); + run_loop.Run(); + async_content_upload_run_loop.Run(); +} + struct AsyncUploadResult { bool success; net::HttpStatusCode response_code;
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc index e6f891c..3dec239d 100644 --- a/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc +++ b/chrome/browser/safe_browsing/download_protection/download_protection_delegate_android.cc
@@ -44,6 +44,10 @@ // Content-Type HTTP header field for the request. const char kProtobufContentType[] = "application/x-protobuf"; +// We sample 1% of allowlisted downloads to still send out download pings if +// other conditions are met. +const double kAllowlistDownloadSampleRate = 0.01; + bool IsDownloadRequestUrlValid(const GURL& url) { return url.is_valid() && url.SchemeIs(url::kHttpsScheme) && google_util::IsGoogleAssociatedDomainUrl(url); @@ -246,9 +250,7 @@ float DownloadProtectionDelegateAndroid::GetAllowlistedDownloadSampleRate() const { - // TODO(chlily): The allowlist is not implemented yet for Android download - // protection. - return 0.0; + return kAllowlistDownloadSampleRate; } float DownloadProtectionDelegateAndroid::GetUnsupportedFileSampleRate(
diff --git a/chrome/browser/segmentation_platform/android/contextual_page_action_controller_android.cc b/chrome/browser/segmentation_platform/android/contextual_page_action_controller_android.cc index 8f406fb..b482f71 100644 --- a/chrome/browser/segmentation_platform/android/contextual_page_action_controller_android.cc +++ b/chrome/browser/segmentation_platform/android/contextual_page_action_controller_android.cc
@@ -43,7 +43,7 @@ segmentation_platform::kContextualPageActionModelLabelDiscounts) { action = AdaptiveToolbarButtonVariant::kDiscounts; } else if (label == segmentation_platform:: - kContextualPageActionModelInputTabGrouping) { + kContextualPageActionModelLabelTabGrouping) { action = AdaptiveToolbarButtonVariant::kTabGrouping; } return action;
diff --git a/chrome/browser/tab_group_suggestion/BUILD.gn b/chrome/browser/tab_group_suggestion/BUILD.gn index 4b58a48..dbc33e2 100644 --- a/chrome/browser/tab_group_suggestion/BUILD.gn +++ b/chrome/browser/tab_group_suggestion/BUILD.gn
@@ -47,6 +47,7 @@ ] deps = [ + "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/strings:components_strings_grd", "//ui/android:ui_java_resources", ]
diff --git a/chrome/browser/tab_group_suggestion/android/java/src/org/chromium/chrome/browser/tab_group_suggestion/toolbar/GroupSuggestionsButtonController.java b/chrome/browser/tab_group_suggestion/android/java/src/org/chromium/chrome/browser/tab_group_suggestion/toolbar/GroupSuggestionsButtonController.java index 82de5d92..e0f7583 100644 --- a/chrome/browser/tab_group_suggestion/android/java/src/org/chromium/chrome/browser/tab_group_suggestion/toolbar/GroupSuggestionsButtonController.java +++ b/chrome/browser/tab_group_suggestion/android/java/src/org/chromium/chrome/browser/tab_group_suggestion/toolbar/GroupSuggestionsButtonController.java
@@ -27,12 +27,12 @@ buttonDrawable, /* TODO(salg): Replace placeholder strings. */ /* contentDescription= */ context.getString( - R.string.data_sharing_shared_tab_groups_activity, 2), - /* actionChipLabelResId= */ R.string.data_sharing_shared_tab_groups_activity, + R.string.tab_group_suggestion_action_chip_label), + /* actionChipLabelResId= */ R.string.tab_group_suggestion_action_chip_label, /* supportsTinting= */ true, /* iphCommandBuilder= */ null, AdaptiveToolbarButtonVariant.TAB_GROUPING, - /* tooltipTextResId= */ R.string.data_sharing_shared_tab_groups_activity); + /* tooltipTextResId= */ R.string.tab_group_suggestion_action_chip_label); } @Override
diff --git a/chrome/browser/tracing/chrome_tracing_delegate.cc b/chrome/browser/tracing/chrome_tracing_delegate.cc index 6d5ce33..bb20d2d 100644 --- a/chrome/browser/tracing/chrome_tracing_delegate.cc +++ b/chrome/browser/tracing/chrome_tracing_delegate.cc
@@ -86,9 +86,10 @@ #if BUILDFLAG(IS_ANDROID) void ChromeTracingDelegate::OnTabModelAdded(TabModel* tab_model) { for (const TabModel* model : TabModelList::models()) { - if (model->GetProfile()->IsOffTheRecord()) + if (model->GetProfile()->IsOffTheRecord()) { latest_incognito_launched_ = base::TimeTicks::Now(); - base::trace_event::EmitNamedTrigger("incognito-start"); + base::trace_event::EmitNamedTrigger("incognito-start"); + } } }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 3f64ac4..5c89e976 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3419,6 +3419,8 @@ "views/frame/windows_caption_button.h", "views/frame/windows_icon_painter.cc", "views/frame/windows_icon_painter.h", + "views/frame/windows_taskbar_icon_updater.cc", + "views/frame/windows_taskbar_icon_updater.h", "views/network_profile_bubble_view.cc", "views/status_icons/status_icon_win.cc", "views/status_icons/status_icon_win.h",
diff --git a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinator.java b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinator.java index b0ce9666..956dedeb 100644 --- a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinator.java +++ b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinator.java
@@ -27,6 +27,7 @@ import org.chromium.base.Log; import org.chromium.base.ObserverList; import org.chromium.base.ResettersForTesting; +import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate; @@ -81,6 +82,7 @@ private int mBrowserControlsToken = TokenHolder.INVALID_TOKEN; private @Nullable AppHeaderState mAppHeaderState; private boolean mIsInUnfocusedDesktopWindow; + private final ObservableSupplierImpl<Boolean> mDesktopWindowTopResumedActivitySupplier; private @DesktopWindowHeuristicResult int mHeuristicResult = DesktopWindowHeuristicResult.UNKNOWN; private @WindowingMode int mWindowingMode = WindowingMode.UNKNOWN; @@ -127,6 +129,14 @@ && savedInstanceState.getBoolean( INSTANCE_STATE_KEY_IS_APP_IN_UNFOCUSED_DW, false); + mDesktopWindowTopResumedActivitySupplier = + new ObservableSupplierImpl<Boolean>(!mIsInUnfocusedDesktopWindow); + mDesktopWindowTopResumedActivitySupplier.addObserver( + (isFocused) -> { + mObservers.forEach( + (observer) -> observer.onActivityFocusStateChanged(isFocused)); + }); + // Initialize mInsetsRectProvider and setup observers. mCaptionBarRectProvider = sInsetsRectProviderForTesting != null @@ -181,6 +191,9 @@ @Override public void onTopResumedActivityChanged(boolean isTopResumedActivity) { mIsInUnfocusedDesktopWindow = !isTopResumedActivity && mIsInDesktopWindow; + if (mIsInDesktopWindow) { + mDesktopWindowTopResumedActivitySupplier.set(isTopResumedActivity); + } } // SaveInstanceStateObserver implementation. @@ -344,14 +357,18 @@ } /** Set states for testing. */ - public void setStateForTesting(boolean isInDesktopWindow, AppHeaderState appHeaderState) { + public void setStateForTesting( + boolean isInDesktopWindow, AppHeaderState appHeaderState, boolean isFocused) { mIsInDesktopWindow = isInDesktopWindow; setEdgeToEdgeState(mIsInDesktopWindow); mAppHeaderState = appHeaderState; - + if (mIsInDesktopWindow) { + mDesktopWindowTopResumedActivitySupplier.set(isFocused); + } for (var observer : mObservers) { observer.onAppHeaderStateChanged(mAppHeaderState); observer.onDesktopWindowingModeChanged(mIsInDesktopWindow); + observer.onActivityFocusStateChanged(isFocused); } } @@ -387,4 +404,8 @@ .setInsets(WindowInsetsCompat.Type.navigationBars(), Insets.NONE) .build(); } + + /* package */ ObservableSupplierImpl<Boolean> getTopResumedActivitySupplierForTesting() { + return mDesktopWindowTopResumedActivitySupplier; + } }
diff --git a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinatorUnitTest.java b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinatorUnitTest.java index a0c1c35..8c9fa88 100644 --- a/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinatorUnitTest.java +++ b/chrome/browser/ui/android/desktop_windowing/java/src/org/chromium/chrome/browser/ui/desktop_windowing/AppHeaderCoordinatorUnitTest.java
@@ -32,6 +32,7 @@ import androidx.core.view.WindowInsetsCompat; import androidx.test.ext.junit.rules.ActivityScenarioRule; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -419,6 +420,20 @@ assertTrue( "Window focus state is not correctly set.", mAppHeaderCoordinator.isInUnfocusedDesktopWindow()); + Assert.assertFalse(mAppHeaderCoordinator.getTopResumedActivitySupplierForTesting().get()); + } + + @Test + public void activityFocusedInDesktopWindow() { + setupWithLeftAndRightBoundingRect(); + notifyInsetsRectConsumer(); + + mAppHeaderCoordinator.onTopResumedActivityChanged(true); + + assertFalse( + "Window focus state is not correctly set.", + mAppHeaderCoordinator.isInUnfocusedDesktopWindow()); + Assert.assertTrue(mAppHeaderCoordinator.getTopResumedActivitySupplierForTesting().get()); } @Test
diff --git a/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.cc b/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.cc index f42fcb9..ee20657 100644 --- a/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.cc +++ b/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/extensions/commands/command_service.h" #include "chrome/browser/extensions/extension_keybinding_registry.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/android/extensions/jni_headers/ExtensionKeybindingRegistryAndroid_jni.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" #include "third_party/jni_zero/jni_zero.h" @@ -21,6 +20,11 @@ #include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/platform_event.h" +// Must come after all headers that specialize FromJniType() / ToJniType(). +#include "chrome/browser/ui/android/extensions/jni_headers/ExtensionKeybindingRegistryAndroid_jni.h" + +namespace extensions { + ExtensionKeybindingRegistryAndroid::ExtensionKeybindingRegistryAndroid( content::BrowserContext* context, ExtensionFilter extension_filter, @@ -61,10 +65,8 @@ // JNI functions -static jlong JNI_ExtensionKeybindingRegistryAndroid_Init( - JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& profile_obj) { - Profile* profile = Profile::FromJavaObject(profile_obj); +static jlong JNI_ExtensionKeybindingRegistryAndroid_Init(JNIEnv* env, + Profile* profile) { ExtensionKeybindingRegistryAndroid* instance = new ExtensionKeybindingRegistryAndroid( profile, extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS, @@ -76,14 +78,14 @@ delete this; } -jboolean ExtensionKeybindingRegistryAndroid::HandleKeyEvent( +bool ExtensionKeybindingRegistryAndroid::HandleKeyEvent( JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& java_key_event) { + const ui::KeyEventAndroid& key_event) { if (is_shortcut_handling_suspended_) { return false; } - ui::PlatformEvent native_event((ui::KeyEventAndroid(env, java_key_event))); + ui::PlatformEvent native_event(key_event); ui::Accelerator accelerator((ui::KeyEvent(native_event))); if (!active_accelerators_.contains(accelerator)) { @@ -92,3 +94,5 @@ return NotifyEventTargets(accelerator); } + +} // namespace extensions
diff --git a/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.h b/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.h index 379b724..67d52e1f 100644 --- a/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.h +++ b/chrome/browser/ui/android/extensions/extension_keybinding_registry_android.h
@@ -7,11 +7,14 @@ #include "chrome/browser/extensions/extension_keybinding_registry.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/events/android/key_event_android.h" namespace content { class BrowserContext; } +namespace extensions { + // This class handles keyboard accelerators for extensions on Android. class ExtensionKeybindingRegistryAndroid : public extensions::ExtensionKeybindingRegistry { @@ -32,9 +35,7 @@ // Handles the key event. It returns whether the key event was handled. It // immediately returns false if the given key event should not intercept. - jboolean HandleKeyEvent( - JNIEnv* env, - const jni_zero::JavaParamRef<jobject>& java_key_event); + bool HandleKeyEvent(JNIEnv* env, const ui::KeyEventAndroid& key_event); private: // Overridden from ExtensionKeybindingRegistry: @@ -48,4 +49,6 @@ bool is_shortcut_handling_suspended_ = false; }; +} // namespace extensions + #endif // CHROME_BROWSER_UI_ANDROID_EXTENSIONS_EXTENSION_KEYBINDING_REGISTRY_ANDROID_H_
diff --git a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionKeybindingRegistryAndroid.java b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionKeybindingRegistryAndroid.java index 2f30b03..a9200c6 100644 --- a/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionKeybindingRegistryAndroid.java +++ b/chrome/browser/ui/android/extensions/java/src/org/chromium/chrome/browser/ui/extensions/ExtensionKeybindingRegistryAndroid.java
@@ -6,6 +6,8 @@ import android.view.KeyEvent; +import org.jni_zero.JNINamespace; +import org.jni_zero.JniType; import org.jni_zero.NativeMethods; import org.chromium.build.annotations.NullMarked; @@ -17,6 +19,7 @@ * ExtensionKeybindingRegistryAndroid object and handles communication between Java and C++. */ @NullMarked +@JNINamespace("extensions") @ServiceImpl(ExtensionKeybindingRegistry.class) public class ExtensionKeybindingRegistryAndroid implements ExtensionKeybindingRegistry { private long mNativeExtensionKeybindingRegistryAndroid; @@ -49,10 +52,12 @@ @NativeMethods interface Natives { - long init(Profile profile); + long init(@JniType("Profile*") Profile profile); void destroy(long nativeExtensionKeybindingRegistryAndroid); - boolean handleKeyEvent(long nativeExtensionKeybindingRegistryAndroid, KeyEvent event); + boolean handleKeyEvent( + long nativeExtensionKeybindingRegistryAndroid, + @JniType("ui::KeyEventAndroid") KeyEvent event); } }
diff --git a/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog_v2.xml b/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog_v2.xml index 0828daf35..8d990ce 100644 --- a/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog_v2.xml +++ b/chrome/browser/ui/android/multiwindow/java/res/layout/instance_switcher_dialog_v2.xml
@@ -50,7 +50,6 @@ <TextView android:id="@+id/max_instance_info" - android:text="@string/max_number_of_windows_instance_switcher_v2" android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java index 9d0f2338..0cb4de73 100644 --- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java +++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
@@ -505,23 +505,14 @@ } if (mNewWindowEnabled) { mMaxInfoView.setVisibility(View.GONE); - return; } else { - int overLimitCount = getTotalInstanceCount() - mMaxInstanceCount + 1; - StringBuilder msgBuilder = new StringBuilder(); - msgBuilder.append( - mContext.getString( - R.string.max_number_of_windows_instance_switcher_v2, - mMaxInstanceCount, - overLimitCount)); - - // Append additional text for inactive list. - if (mIsInactiveListShowing) { - msgBuilder - .append(" ") - .append(mContext.getString(R.string.persisted_instance_deletion_message)); - } - mMaxInfoView.setText(msgBuilder.toString()); + @StringRes + int textRes = + mIsInactiveListShowing + ? R.string.max_number_of_windows_instance_switcher_v2_inactive_tab + : R.string.max_number_of_windows_instance_switcher_v2_active_tab; + String text = mContext.getString(textRes, mMaxInstanceCount, mMaxInstanceCount - 1); + mMaxInfoView.setText(text); mMaxInfoView.setVisibility(View.VISIBLE); } }
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java index 861bd0f..717b179 100644 --- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java +++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
@@ -478,7 +478,10 @@ String activeMaxInfoText = mActivityTestRule .getActivity() - .getString(R.string.max_number_of_windows_instance_switcher_v2, 5, 2); + .getString( + R.string.max_number_of_windows_instance_switcher_v2_active_tab, + 5, + 4); onView(withText(activeMaxInfoText)).inRoot(isDialog()).check(matches(isDisplayed())); // Verify + new window command is not added to the dialog. @@ -487,11 +490,12 @@ // Switch to the inactive instance tab, verify we show max instance info message in inactive // list and close the inactive instance. String inactiveMaxInfoText = - activeMaxInfoText - + " " - + mActivityTestRule - .getActivity() - .getString(R.string.persisted_instance_deletion_message); + mActivityTestRule + .getActivity() + .getString( + R.string.max_number_of_windows_instance_switcher_v2_inactive_tab, + 5, + 4); onView(allOf(withText("Inactive (1)"), isDescendantOfA(withId(R.id.tabs)))) .perform(click()); onView(withText(inactiveMaxInfoText)).inRoot(isDialog()).check(matches(isDisplayed())); @@ -502,7 +506,10 @@ activeMaxInfoText = mActivityTestRule .getActivity() - .getString(R.string.max_number_of_windows_instance_switcher_v2, 5, 1); + .getString( + R.string.max_number_of_windows_instance_switcher_v2_active_tab, + 5, + 4); onView(withText(activeMaxInfoText)).inRoot(isDialog()).check(matches(isDisplayed())); // Close an active instance.
diff --git a/chrome/browser/ui/android/omnibox/java/res/values/styles.xml b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml index 51434bd..befc207 100644 --- a/chrome/browser/ui/android/omnibox/java/res/values/styles.xml +++ b/chrome/browser/ui/android/omnibox/java/res/values/styles.xml
@@ -6,8 +6,10 @@ --> <resources xmlns:tools="http://schemas.android.com/tools"> - - <style name="Base.Theme.Chromium.TabbedMode" parent="Theme.Chromium.WithWindowAnimation" /> + <style name="Base.Theme.Chromium.TabbedMode" parent="Theme.Chromium.WithWindowAnimation"> + <item name="android:statusBarColor">@macro/default_bg_color</item> + <item name="android:windowLightStatusBar">@bool/window_light_status_bar</item> + </style> <style name="Theme.Chromium.TabbedMode" parent="Base.Theme.Chromium.TabbedMode" /> <!-- Omnibox -->
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java index a4e2d8a..2ef882b 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
@@ -12,7 +12,6 @@ import android.view.ActionMode; import androidx.annotation.ColorInt; -import androidx.annotation.RequiresApi; import com.google.android.material.color.MaterialColors; @@ -153,7 +152,6 @@ view.setHighlightColor(highlightColor); } - @RequiresApi(api = Build.VERSION_CODES.Q) private static void updateCursorAndSelectHandleColor(UrlBar view, boolean useIncognitoColors) { // These get* methods may fail on some devices, so we're calling all of them before // applying tint to any of the drawables. See https://crbug.com/1263630.
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index d67bc05..2296900 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -5328,11 +5328,11 @@ <message name="IDS_MAX_NUMBER_OF_WINDOWS" desc="Toast message for when the user has tried to start more than 5 instances of Chrome window."> You can have up to 5 windows. </message> - <message name="IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2" desc="Message to notify the user that the total number of persisted instances exceeds the window limit."> - You can have up to <ph name="MAX_WINDOW_COUNT">%1$d</ph> total windows. To restore a window, close <ph name="WINDOW_COUNT">%2$d</ph> active or inactive windows. + <message name="IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_ACTIVE_TAB" desc="Message to notify the user that a new window cannot be created because the total number of persisted instances exceeds the window limit."> + You can have up to <ph name="MAX_WINDOW_COUNT">%1$d</ph> total windows. To open a new window, reduce the total number of windows across active and inactive to <ph name="MAX_WINDOW_COUNT_MINUS_ONE">%2$d</ph> or fewer. </message> - <message name="IDS_PERSISTED_INSTANCE_DELETION_MESSAGE" desc="Message to notify the user about permanent deletion of persisted instances."> - Inactive windows are permanently deleted after 6 months of being inactive. + <message name="IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_INACTIVE_TAB" desc="Message to notify the user thata window cannot be restored because the total number of persisted instances exceeds the window limit."> + You can have up to <ph name="MAX_WINDOW_COUNT">%1$d</ph> total windows. To restore a new window, reduce the total number of windows across active and inactive to <ph name="MAX_WINDOW_COUNT_MINUS_ONE">%2$d</ph> or fewer. Inactive windows are deleted after 6 months. </message> <message name="IDS_TAB_DROPPED_DIFFERENT_MODEL" desc="Toast that appears when a tab is dropped into tab strip with a different profile (regular v.s. incognito)."> You can find all open tabs in the tab switcher @@ -7224,6 +7224,12 @@ <message name="IDS_DEFAULT_BROWSER_PROMO_MESSAGE_SETTINGS_BUTTON" desc="Text that displayed on button that allows the user to open Android settings to set a default browser."> Settings </message> + + <!-- Tab group suggestions --> + <message name="IDS_TAB_GROUP_SUGGESTION_ACTION_CHIP_LABEL" desc="The label for the action chip for tab group suggestions in the top toolbar."> + Group tabs + </message> + </messages> </release> </grit>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2.png.sha1 deleted file mode 100644 index 442902d..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -6db7a8afc9c2c48430e122d363b1d4f252dbbae2 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_ACTIVE_TAB.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_ACTIVE_TAB.png.sha1 new file mode 100644 index 0000000..07ddb8a9 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_ACTIVE_TAB.png.sha1
@@ -0,0 +1 @@ +e2207528a5e55d5f677c225611981bedac3b74bf \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_INACTIVE_TAB.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_INACTIVE_TAB.png.sha1 new file mode 100644 index 0000000..3bc4cea4 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MAX_NUMBER_OF_WINDOWS_INSTANCE_SWITCHER_V2_INACTIVE_TAB.png.sha1
@@ -0,0 +1 @@ +3ca9da8ed3113bc9a4fd02d02a77580095342918 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PERSISTED_INSTANCE_DELETION_MESSAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PERSISTED_INSTANCE_DELETION_MESSAGE.png.sha1 deleted file mode 100644 index 442902d..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PERSISTED_INSTANCE_DELETION_MESSAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -6db7a8afc9c2c48430e122d363b1d4f252dbbae2 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TAB_GROUP_SUGGESTION_ACTION_CHIP_LABEL.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TAB_GROUP_SUGGESTION_ACTION_CHIP_LABEL.png.sha1 new file mode 100644 index 0000000..d36ef66 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_TAB_GROUP_SUGGESTION_ACTION_CHIP_LABEL.png.sha1
@@ -0,0 +1 @@ +fbcf9fc0f10b054aa88dd69511c664a6e0081566 \ No newline at end of file
diff --git a/chrome/browser/ui/ash/BUILD.gn b/chrome/browser/ui/ash/BUILD.gn index 51adf5a..c1c493b 100644 --- a/chrome/browser/ui/ash/BUILD.gn +++ b/chrome/browser/ui/ash/BUILD.gn
@@ -22,6 +22,7 @@ "//chrome/browser", "//chrome/browser/ash/crosapi:test_support", "//chrome/browser/ui", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/exclusive_access", "//chrome/browser/ui/exclusive_access:test_support", "//chrome/browser/ui/views/frame:immersive_mode_controller",
diff --git a/chrome/browser/ui/ash/DEPS b/chrome/browser/ui/ash/DEPS index 0d9c9441..3e41598 100644 --- a/chrome/browser/ui/ash/DEPS +++ b/chrome/browser/ui/ash/DEPS
@@ -29,6 +29,7 @@ "+chrome/browser/ui/ash", "+chrome/browser/ui/browser_commands.h", "+chrome/browser/ui/browser.h", + "+chrome/browser/ui/browser_window/public/browser_window_features.h", "+chrome/browser/ui/exclusive_access", "+chrome/browser/ui/views", "+chrome/test/base",
diff --git a/chrome/browser/ui/ash/shell_delegate/BUILD.gn b/chrome/browser/ui/ash/shell_delegate/BUILD.gn index 02b165b..5d0ffb36 100644 --- a/chrome/browser/ui/ash/shell_delegate/BUILD.gn +++ b/chrome/browser/ui/ash/shell_delegate/BUILD.gn
@@ -52,6 +52,7 @@ "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/views", "//chrome/browser/ui/views/frame:immersive_mode_controller", + "//chrome/browser/ui/webui/ash/diagnostics_dialog", "//chrome/browser/web_applications", "//chrome/common", "//chromeos/ash/components/audio",
diff --git a/chrome/browser/ui/ash/shell_delegate/DEPS b/chrome/browser/ui/ash/shell_delegate/DEPS index b9130b5..d2b5b73f 100644 --- a/chrome/browser/ui/ash/shell_delegate/DEPS +++ b/chrome/browser/ui/ash/shell_delegate/DEPS
@@ -58,6 +58,7 @@ "+chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h", "+chrome/browser/ui/views/frame", "+chrome/browser/ui/views/tabs", + "+chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h", "+chrome/browser/ui/webui/tab_strip", "+chrome/browser/web_applications", "+chrome/common",
diff --git a/chrome/browser/ui/ash/shell_delegate/chrome_shell_delegate.cc b/chrome/browser/ui/ash/shell_delegate/chrome_shell_delegate.cc index 555bb4a..3d94ce98 100644 --- a/chrome/browser/ui/ash/shell_delegate/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/shell_delegate/chrome_shell_delegate.cc
@@ -72,6 +72,7 @@ #include "chrome/browser/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h" #include "chrome/browser/web_applications/web_app_provider.h" @@ -385,6 +386,15 @@ ash::assistant::AssistantAllowedState::ALLOWED) { ash::AssistantState::Get()->NotifyLockedFullScreenStateChanged(locked); } + + // If a window is entering locked fullscreen, then we should close any + // diagnostics dialog that may be open, since it would show on top of the + // fullscreen window. There is no need to close it when leaving locked + // fullscreen, since it is OK for the dialog to be open after exiting locked + // fullscreen in case the dialog was somehow opened during locked fullscreen. + if (locked) { + ash::DiagnosticsDialog::MaybeCloseExistingDialog(); + } } bool ChromeShellDelegate::IsUiDevToolsStarted() const {
diff --git a/chrome/browser/ui/ash/test/accelerator_metadata_unittest.cc b/chrome/browser/ui/ash/test/accelerator_metadata_unittest.cc index 40299ae..6f87f81 100644 --- a/chrome/browser/ui/ash/test/accelerator_metadata_unittest.cc +++ b/chrome/browser/ui/ash/test/accelerator_metadata_unittest.cc
@@ -6,7 +6,6 @@ #include "ash/test/ash_test_util.h" #include "ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h" -#include "base/hash/md5_boringssl.h" #include "base/strings/stringprintf.h" #include "base/strings/to_string.h" #include "build/branding_buildflags.h"
diff --git a/chrome/browser/ui/ash/test_util.cc b/chrome/browser/ui/ash/test_util.cc index f4a6ee6..163e8aa 100644 --- a/chrome/browser/ui/ash/test_util.cc +++ b/chrome/browser/ui/ash/test_util.cc
@@ -14,6 +14,7 @@ #include "ash/wm/window_pin_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h" @@ -154,7 +155,8 @@ Browser* browser, content::WebContents* web_contents) { ui_test_utils::FullscreenWaiter waiter(browser, {.tab_fullscreen = false}); - browser->exclusive_access_manager() + browser->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ExitFullscreenModeForTab(web_contents); waiter.Wait();
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index f9eabd3..5a2c3e1 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -52,8 +52,6 @@ #include "chrome/browser/defaults.h" #include "chrome/browser/devtools/devtools_toggle_action.h" #include "chrome/browser/devtools/devtools_window.h" -#include "chrome/browser/download/bubble/download_bubble_ui_controller.h" -#include "chrome/browser/download/bubble/download_display_controller.h" #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/extensions/extension_ui_util.h" @@ -742,15 +740,6 @@ session_service->WindowOpened(this); } - exclusive_access_manager_ = std::make_unique<ExclusiveAccessManager>( - window_->GetExclusiveAccessContext()); - - if (window_->GetDownloadBubbleUIController()) { - window_->GetDownloadBubbleUIController() - ->GetDownloadDisplayController() - ->ListenToFullScreenChanges(); - } - // Initialize the browser features that rely on the browser window now that it // is initialized. features_->InitPostWindowConstruction(this); @@ -789,7 +778,6 @@ // Destroy ExclusiveAccessManager, which depends on `window_` which may be // destroyed by RemoveBrowser(). - exclusive_access_manager_.reset(); BrowserList::RemoveBrowser(this); // If closing the window is going to trigger a shutdown, then we need to @@ -1293,7 +1281,7 @@ } ExclusiveAccessManager* Browser::GetExclusiveAccessManager() { - return exclusive_access_manager(); + return GetFeatures().exclusive_access_manager(); } ImmersiveModeController* Browser::GetImmersiveModeController() { @@ -1498,7 +1486,9 @@ // Browser, Tab adding/showing functions: void Browser::WindowFullscreenStateChanged() { - exclusive_access_manager_->fullscreen_controller() + browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() ->WindowFullscreenStateChanged(); command_controller_->FullscreenStateChanged(); UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TOGGLE_FULLSCREEN); @@ -1518,7 +1508,9 @@ // Browser, Assorted browser commands: void Browser::ToggleFullscreenModeWithExtension(const GURL& extension_url) { - exclusive_access_manager_->fullscreen_controller() + browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() ->ToggleBrowserFullscreenModeWithExtension(extension_url); } @@ -1881,7 +1873,8 @@ // Forward keyboard events to the manager for fullscreen / mouse lock. This // may consume the event (e.g., Esc exits fullscreen mode). // TODO(koz): Write a test for this http://crbug.com/100441. - if (exclusive_access_manager_->HandleUserKeyEvent(event)) { + if (browser_window_features()->exclusive_access_manager()->HandleUserKeyEvent( + event)) { return content::KeyboardEventProcessingResult::HANDLED; } @@ -2006,7 +1999,9 @@ const content::MediaPlayerWatchTime& watch_time) {} bool Browser::IsPointerLocked() const { - return exclusive_access_manager_->pointer_lock_controller() + return browser_window_features() + ->exclusive_access_manager() + ->pointer_lock_controller() ->IsPointerLocked(); } @@ -2155,8 +2150,9 @@ const blink::mojom::WindowFeatures& window_features, bool user_gesture, bool* was_blocked) { - FullscreenController* fullscreen_controller = - exclusive_access_manager_->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller(); #if BUILDFLAG(IS_MAC) // On the Mac, the convention is to turn popups into new tabs when in browser // fullscreen mode. Only worry about user-initiated fullscreen as showing a @@ -2275,7 +2271,7 @@ // without explicit user input events during window state changes. if (type != ui::EventType::kMouseEntered && !exited && !event.IsSynthesized()) { - exclusive_access_manager_->OnUserInput(); + browser_window_features()->exclusive_access_manager()->OnUserInput(); } // Mouse motion events update the status bubble, if it exists. @@ -2613,20 +2609,26 @@ return false; } - return exclusive_access_manager_->fullscreen_controller() + return browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() ->CanEnterFullscreenModeForTab(requesting_frame); } void Browser::EnterFullscreenModeForTab( content::RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) { - exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( - requesting_frame, options.display_id); + browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab(requesting_frame, options.display_id); } void Browser::ExitFullscreenModeForTab(WebContents* web_contents) { - exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab( - web_contents); + browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() + ->ExitFullscreenModeForTab(web_contents); } bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) { @@ -2637,8 +2639,10 @@ content::FullscreenState Browser::GetFullscreenState( const WebContents* web_contents) const { - return exclusive_access_manager_->fullscreen_controller()->GetFullscreenState( - web_contents); + return browser_window_features() + ->exclusive_access_manager() + ->fullscreen_controller() + ->GetFullscreenState(web_contents); } blink::mojom::DisplayMode Browser::GetDisplayMode( @@ -2808,28 +2812,39 @@ void Browser::RequestPointerLock(WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) { - exclusive_access_manager_->pointer_lock_controller()->RequestToLockPointer( - web_contents, user_gesture, last_unlocked_by_target); + browser_window_features() + ->exclusive_access_manager() + ->pointer_lock_controller() + ->RequestToLockPointer(web_contents, user_gesture, + last_unlocked_by_target); } void Browser::LostPointerLock() { - exclusive_access_manager_->pointer_lock_controller() + browser_window_features() + ->exclusive_access_manager() + ->pointer_lock_controller() ->ExitExclusiveAccessToPreviousState(); } bool Browser::IsWaitingForPointerLockPrompt(WebContents* web_contents) { - return exclusive_access_manager_->pointer_lock_controller() + return browser_window_features() + ->exclusive_access_manager() + ->pointer_lock_controller() ->IsWaitingForPointerLockPrompt(web_contents); } void Browser::RequestKeyboardLock(WebContents* web_contents, bool esc_key_locked) { - exclusive_access_manager_->keyboard_lock_controller()->RequestKeyboardLock( - web_contents, esc_key_locked); + browser_window_features() + ->exclusive_access_manager() + ->keyboard_lock_controller() + ->RequestKeyboardLock(web_contents, esc_key_locked); } void Browser::CancelKeyboardLockRequest(WebContents* web_contents) { - exclusive_access_manager_->keyboard_lock_controller() + browser_window_features() + ->exclusive_access_manager() + ->keyboard_lock_controller() ->CancelKeyboardLockRequest(web_contents); } @@ -3078,7 +3093,7 @@ page_load_metrics::MetricsWebContentsObserver::FromWebContents(contents); metrics_observer->WebContentsWillSoonBeDestroyed(); - exclusive_access_manager_->OnTabClosing(contents); + browser_window_features()->exclusive_access_manager()->OnTabClosing(contents); SessionServiceBase* service = GetAppropriateSessionServiceForProfile(this); if (service) { @@ -3101,7 +3116,8 @@ } void Browser::OnTabDeactivated(WebContents* contents) { - exclusive_access_manager_->OnTabDeactivated(contents); + browser_window_features()->exclusive_access_manager()->OnTabDeactivated( + contents); SearchTabHelper::FromWebContents(contents)->OnTabDeactivated(); // Save what the user's currently typing, so it can be restored when we @@ -3154,7 +3170,8 @@ // is updated. window_->OnActiveTabChanged(old_contents, new_contents, index, reason); - exclusive_access_manager_->OnTabDetachedFromView(old_contents); + browser_window_features()->exclusive_access_manager()->OnTabDetachedFromView( + old_contents); // If we have any update pending, do it now. if (chrome_updater_factory_.HasWeakPtrs() && old_contents) { @@ -3218,7 +3235,8 @@ did_active_tab_change_callback_list_.Notify(this); } TabDetachedAtImpl(old_contents, was_active, DETACH_TYPE_REPLACE); - exclusive_access_manager_->OnTabClosing(old_contents); + browser_window_features()->exclusive_access_manager()->OnTabClosing( + old_contents); SessionServiceBase* session_service = GetAppropriateSessionServiceForProfile(this); if (session_service) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index 88031e2f..0d917abe 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -71,7 +71,6 @@ class BrowserView; class BrowserWindow; class BrowserWindowFeatures; -class ExclusiveAccessManager; class FindBarController; class OverscrollPrefManager; class Profile; @@ -788,10 +787,6 @@ // Called each time the browser window is shown. void OnWindowDidShow(); - ExclusiveAccessManager* exclusive_access_manager() { - return exclusive_access_manager_.get(); - } - bool ShouldRunUnloadListenerBeforeClosing(content::WebContents* web_contents); bool RunUnloadListenerBeforeClosing(content::WebContents* web_contents); @@ -1419,8 +1414,6 @@ BookmarkBar::State bookmark_bar_state_; - std::unique_ptr<ExclusiveAccessManager> exclusive_access_manager_; - std::unique_ptr<BrowserActions> browser_actions_; std::unique_ptr<chrome::BrowserCommandController> command_controller_;
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index 611097e..6f60bda 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -68,6 +68,7 @@ #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_ui_prefs.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/search/search_tab_helper.h" @@ -2607,10 +2608,13 @@ auto* app_contents = app_browser->tab_strip_model()->GetActiveWebContents(); CheckDisplayModeMQ(u"standalone", app_contents); - app_browser->exclusive_access_manager()->context()->EnterFullscreen( - url::Origin(), - EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, - display::kInvalidDisplayId); + app_browser->GetFeatures() + .exclusive_access_manager() + ->context() + ->EnterFullscreen( + url::Origin(), + EXCLUSIVE_ACCESS_BUBBLE_TYPE_BROWSER_FULLSCREEN_EXIT_INSTRUCTION, + display::kInvalidDisplayId); // Sync navigation just to make sure IPC has passed (updated // display mode is delivered to RP).
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 6ec4879..6238011 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -2265,7 +2265,8 @@ void ToggleFullscreenMode(Browser* browser, bool user_initiated) { DCHECK(browser); - browser->exclusive_access_manager() + browser->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ToggleBrowserFullscreenMode(user_initiated); }
diff --git a/chrome/browser/ui/browser_navigator_iwa_browsertest.cc b/chrome/browser/ui/browser_navigator_iwa_browsertest.cc index af88479..43c3278 100644 --- a/chrome/browser/ui/browser_navigator_iwa_browsertest.cc +++ b/chrome/browser/ui/browser_navigator_iwa_browsertest.cc
@@ -21,6 +21,8 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_browsertest.h" #include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/browser/ui/web_applications/app_browser_controller.h" +#include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h" #include "chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_install_source.h" #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_trust_checker.h" @@ -34,6 +36,7 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/custom_handlers/protocol_handler.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/web_package/test_support/signed_web_bundles/web_bundle_signer.h" #include "content/public/common/content_features.h" @@ -98,7 +101,6 @@ void SetUpOnMainThread() override { BrowserNavigatorTest::SetUpOnMainThread(); - web_app::test::WaitUntilReady( web_app::WebAppProvider::GetForTest(profile())); } @@ -107,10 +109,12 @@ protected: void InstallBundles() { - app1_ = - web_app::IsolatedWebAppBuilder( - web_app::ManifestBuilder().SetName("app-1.0.0").SetVersion("1.0.0")) - .BuildBundle(); + app1_ = web_app::IsolatedWebAppBuilder( + web_app::ManifestBuilder() + .SetName("app-1.0.0") + .SetVersion("1.0.0") + .AddProtocolHandler("web+meow", "/index.html?params=%s")) + .BuildBundle(); url_info1_ = std::make_unique<web_app::IsolatedWebAppUrlInfo>( *app1_->Install(profile())); @@ -249,6 +253,45 @@ #endif } +#if BUILDFLAG(IS_CHROMEOS) +IN_PROC_BROWSER_TEST_F(BrowserNavigatorIwaTest, WindowOpenProtocol) { + ASSERT_NO_FATAL_FAILURE(InstallBundles()); + + { + // Eliminate all prompts/guards along the way. + ExternalProtocolHandler::PermitLaunchUrl(); + ExternalProtocolHandler::SetBlockState("web+meow", url_info2_->origin(), + ExternalProtocolHandler::DONT_BLOCK, + profile()); + base::test::TestFuture<void> future; + web_app::WebAppProvider::GetForWebApps(profile()) + ->scheduler() + .UpdateProtocolHandlerUserApproval(url_info1_->app_id(), "web+meow", + web_app::ApiApprovalState::kAllowed, + future.GetCallback()); + ASSERT_TRUE(future.Wait()); + } + + // Open a protocol url from an app frame of IWA2. + auto* rfh = web_app::OpenIsolatedWebApp(profile(), url_info2_->app_id()); + + GURL remapped_url = + custom_handlers::ProtocolHandler::CreateProtocolHandler( + "web+meow", + url_info1_->origin().GetURL().Resolve("/index.html?params=%s")) + .TranslateUrl(GURL("web+meow://hru")); + + ui_test_utils::UrlLoadObserver observer(remapped_url); + ASSERT_THAT(content::EvalJs(rfh, "window.open('web+meow://hru')"), + content::EvalJsResult::IsOk()); + observer.Wait(); + + ASSERT_TRUE(web_app::AppBrowserController::IsForWebApp( + chrome::FindBrowserWithTab(observer.web_contents()), + url_info1_->app_id())); +} +#endif + class BrowserNavigatorIwaNewTabTest : public BrowserNavigatorIwaTest, public ::testing::WithParamInterface<WindowOpenDisposition> {};
diff --git a/chrome/browser/ui/browser_window/BUILD.gn b/chrome/browser/ui/browser_window/BUILD.gn index fe9d1b818..b4c53ef9 100644 --- a/chrome/browser/ui/browser_window/BUILD.gn +++ b/chrome/browser/ui/browser_window/BUILD.gn
@@ -48,6 +48,7 @@ "//chrome/browser/profiles:profile", "//chrome/browser/ui:ui_features", "//chrome/browser/ui/commerce", + "//chrome/browser/ui/exclusive_access", "//chrome/browser/ui/extensions", "//chrome/browser/ui/find_bar:find_bar", "//chrome/browser/ui/lens",
diff --git a/chrome/browser/ui/browser_window/browser_window_features.cc b/chrome/browser/ui/browser_window/browser_window_features.cc index 6a2fca49..c570769 100644 --- a/chrome/browser/ui/browser_window/browser_window_features.cc +++ b/chrome/browser/ui/browser_window/browser_window_features.cc
@@ -13,6 +13,8 @@ #include "chrome/browser/collaboration/collaboration_service_factory.h" #include "chrome/browser/commerce/shopping_service_factory.h" #include "chrome/browser/download/bubble/download_bubble_prefs.h" +#include "chrome/browser/download/bubble/download_bubble_ui_controller.h" +#include "chrome/browser/download/bubble/download_display_controller.h" #include "chrome/browser/extensions/browser_extension_window_controller.h" #include "chrome/browser/extensions/manifest_v2_experiment_manager.h" #include "chrome/browser/extensions/mv2_experiment_stage.h" @@ -29,6 +31,7 @@ #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" #include "chrome/browser/ui/browser_window/public/desktop_browser_window_capabilities.h" #include "chrome/browser/ui/commerce/product_specifications_entry_point_controller.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/extensions/mv2_disabled_dialog_controller.h" #include "chrome/browser/ui/find_bar/find_bar.h" #include "chrome/browser/ui/find_bar/find_bar_controller.h" @@ -89,6 +92,10 @@ #include "chrome/browser/ui/pdf/infobar/pdf_infobar_controller.h" #endif +#if BUILDFLAG(IS_WIN) +#include "chrome/browser/ui/views/frame/windows_taskbar_icon_updater.h" +#endif + #if BUILDFLAG(ENABLE_GLIC) #include "chrome/browser/glic/browser_ui/glic_button_controller.h" #include "chrome/browser/glic/browser_ui/glic_iph_controller.h" @@ -244,6 +251,15 @@ std::make_unique<DesktopBrowserWindowCapabilities>( browser, browser->window(), browser->GetUnownedUserDataHost()); + exclusive_access_manager_ = std::make_unique<ExclusiveAccessManager>( + browser->window()->GetExclusiveAccessContext()); + + // This code needs exclusive access manager to be initialized. + if (download_toolbar_ui_controller_) { + download_toolbar_ui_controller_->display_controller() + ->ListenToFullScreenChanges(); + } + // Features that are only enabled for normal browser windows (e.g. a window // with an omnibox and a tab strip). By default most features should be // instantiated in this block. @@ -399,6 +415,11 @@ std::make_unique<new_tab_footer::NewTabFooterController>( browser_view->browser(), browser_view->new_tab_footer_web_view()); } + +#if BUILDFLAG(IS_WIN) + windows_taskbar_icon_updater_ = + std::make_unique<WindowsTaskbarIconUpdater>(*browser_view); +#endif } void BrowserWindowFeatures::TearDownPreBrowserWindowDestruction() { @@ -446,6 +467,10 @@ find_bar_controller_.reset(); split_tab_scrim_controller_.reset(); + +#if BUILDFLAG(IS_WIN) + windows_taskbar_icon_updater_.reset(); +#endif } SidePanelUI* BrowserWindowFeatures::side_panel_ui() {
diff --git a/chrome/browser/ui/browser_window/public/browser_window_features.h b/chrome/browser/ui/browser_window/public/browser_window_features.h index 41fe189..439f407 100644 --- a/chrome/browser/ui/browser_window/public/browser_window_features.h +++ b/chrome/browser/ui/browser_window/public/browser_window_features.h
@@ -29,6 +29,7 @@ class CookieControlsBubbleCoordinator; class DesktopBrowserWindowCapabilities; class DownloadToolbarUIController; +class ExclusiveAccessManager; class FindBarController; class HistorySidePanelCoordinator; class LocationBarModel; @@ -46,6 +47,10 @@ class ToastService; class TranslateBubbleController; +#if BUILDFLAG(IS_WIN) +class WindowsTaskbarIconUpdater; +#endif + #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) namespace pdf::infobar { class PdfInfoBarController; @@ -304,6 +309,10 @@ // Returns true if a FindBarController exists for this browser window. bool HasFindBarController() const; + ExclusiveAccessManager* exclusive_access_manager() { + return exclusive_access_manager_.get(); + } + protected: BrowserWindowFeatures(); @@ -329,6 +338,8 @@ std::unique_ptr<commerce::ProductSpecificationsEntryPointController> product_specifications_entry_point_controller_; + std::unique_ptr<ExclusiveAccessManager> exclusive_access_manager_; + std::unique_ptr<lens::LensOverlayEntryPointController> lens_overlay_entry_point_controller_; @@ -431,6 +442,10 @@ std::unique_ptr<split_tabs::SplitTabScrimController> split_tab_scrim_controller_; + +#if BUILDFLAG(IS_WIN) + std::unique_ptr<WindowsTaskbarIconUpdater> windows_taskbar_icon_updater_; +#endif }; #endif // CHROME_BROWSER_UI_BROWSER_WINDOW_PUBLIC_BROWSER_WINDOW_FEATURES_H_
diff --git a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm index 497de63..3b33e31a 100644 --- a/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm +++ b/chrome/browser/ui/cocoa/touchbar/browser_window_default_touch_bar_unittest.mm
@@ -15,6 +15,7 @@ #include "chrome/browser/search_engines/template_url_service_factory_test_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/cocoa/test/cocoa_test_helper.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -132,8 +133,10 @@ }; // Set to tab fullscreen. - FullscreenController* fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); fullscreen_controller->set_is_tab_fullscreen_for_testing(true); EXPECT_TRUE(fullscreen_controller->IsTabFullscreen());
diff --git a/chrome/browser/ui/exclusive_access/BUILD.gn b/chrome/browser/ui/exclusive_access/BUILD.gn index 5e07c359..19708e2 100644 --- a/chrome/browser/ui/exclusive_access/BUILD.gn +++ b/chrome/browser/ui/exclusive_access/BUILD.gn
@@ -90,6 +90,7 @@ ] public_deps = [ ":exclusive_access", + "//chrome/browser/ui/browser_window", "//chrome/test:test_support", "//chrome/test:test_support_ui", "//content/test:test_support",
diff --git a/chrome/browser/ui/exclusive_access/exclusive_access_test.cc b/chrome/browser/ui/exclusive_access/exclusive_access_test.cc index 97943912..9a859ce 100644 --- a/chrome/browser/ui/exclusive_access/exclusive_access_test.cc +++ b/chrome/browser/ui/exclusive_access/exclusive_access_test.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" @@ -284,7 +285,7 @@ } ExclusiveAccessManager* ExclusiveAccessTest::GetExclusiveAccessManager() { - return browser()->exclusive_access_manager(); + return browser()->GetFeatures().exclusive_access_manager(); } void ExclusiveAccessTest::SetEscRepeatWindowLength(
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc index ba221cbe..970f346 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_browsertest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" @@ -49,7 +50,8 @@ base::RunLoop outer_loop; auto wait_for_state = base::BindRepeating( [](base::RunLoop* outer_loop, Browser* browser) { - ExclusiveAccessManager* manager = browser->exclusive_access_manager(); + ExclusiveAccessManager* manager = + browser->GetFeatures().exclusive_access_manager(); if (manager->context()->IsExclusiveAccessBubbleDisplayed()) { outer_loop->Quit(); }
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc index b4f79e2..aaac1ca 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" @@ -109,7 +110,8 @@ void PressKeyAndWaitForPointerLockRequest(ui::KeyboardCode key_code) { base::RunLoop run_loop; browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->pointer_lock_controller() ->set_lock_state_callback_for_test(run_loop.QuitClosure()); ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key_code, false, @@ -123,7 +125,10 @@ } PointerLockController* pointer_lock_controller = - browser()->exclusive_access_manager()->pointer_lock_controller(); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->pointer_lock_controller(); base::RunLoop run_loop; pointer_lock_controller->set_bubble_hide_callback_for_test( base::BindRepeating( @@ -703,7 +708,8 @@ { base::RunLoop run_loop; browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->pointer_lock_controller() ->set_lock_state_callback_for_test(run_loop.QuitClosure()); Reload();
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc index 997f66fd..dc15c76 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_test.cc
@@ -10,6 +10,7 @@ #include "build/build_config.h" #include "chrome/browser/fullscreen.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_test.h" @@ -524,7 +525,10 @@ void FullscreenControllerStateTest::TearDown() {} FullscreenController* FullscreenControllerStateTest::GetFullscreenController() { - return GetBrowser()->exclusive_access_manager()->fullscreen_controller(); + return GetBrowser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); } std::string FullscreenControllerStateTest::GetTransitionTableAsString() const {
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc index ac69e19a..c22702e 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -8,6 +8,7 @@ #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -426,7 +427,8 @@ ChangeWindowFullscreenState(); EXPECT_EQ(EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE, browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->GetExclusiveAccessExitBubbleType()); } @@ -866,7 +868,9 @@ second_browser_window.get())); AddTab(second_browser.get(), GURL(url::kAboutBlankURL)); FullscreenController* second_fullscreen_controller = - second_browser->exclusive_access_manager()->fullscreen_controller(); + second_browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); // Detach the tab from the first browser window and attach it to the second. // The tab should remain in fullscreen mode and neither browser window should
diff --git a/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc b/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc index ffe04da8..af6b0ad1 100644 --- a/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc +++ b/chrome/browser/ui/fullscreen_keyboard_browsertest_base.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -70,7 +71,8 @@ bool FullscreenKeyboardBrowserTestBase::IsInBrowserFullscreen() const { return GetActiveBrowser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsFullscreenForBrowser(); } @@ -189,8 +191,11 @@ void FullscreenKeyboardBrowserTestBase::SendFullscreenShortcutAndWait() { // On MacOSX, entering and exiting fullscreen are not synchronous. So we wait // for the observer to notice the change of fullscreen state. - bool current = - GetActiveBrowser()->exclusive_access_manager()->context()->IsFullscreen(); + bool current = GetActiveBrowser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->IsFullscreen(); ui_test_utils::FullscreenWaiter waiter( GetActiveBrowser(), current ? ui_test_utils::FullscreenWaiter::kNoFullscreen
diff --git a/chrome/browser/ui/fullscreen_util_mac_browsertest.cc b/chrome/browser/ui/fullscreen_util_mac_browsertest.cc index f0b922b..0390baf 100644 --- a/chrome/browser/ui/fullscreen_util_mac_browsertest.cc +++ b/chrome/browser/ui/fullscreen_util_mac_browsertest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" @@ -36,7 +37,10 @@ } FullscreenController* GetFullscreenController() { - return browser()->exclusive_access_manager()->fullscreen_controller(); + return browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); } bool IsBrowserFullscreen() {
diff --git a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc index 93ec5eb..55510023 100644 --- a/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc +++ b/chrome/browser/ui/keyboard_lock_interactive_browsertest.cc
@@ -7,6 +7,7 @@ #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/fullscreen_keyboard_browsertest_base.h" #include "chrome/test/base/in_process_browser_test.h" @@ -113,7 +114,7 @@ #endif ExclusiveAccessManager* GetExclusiveAccessManager() { - return browser()->exclusive_access_manager(); + return browser()->GetFeatures().exclusive_access_manager(); } KeyboardLockController* GetKeyboardLockController() {
diff --git a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc index 70a7ee7..74b24f6 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
@@ -5251,8 +5251,10 @@ [&]() { return controller->state() == State::kOverlay; })); // Enter into fullscreen mode. - FullscreenController* fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); content::WebContents* tab_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); fullscreen_controller->EnterFullscreenModeForTab( @@ -5277,8 +5279,10 @@ IDC_CONTENT_CONTEXT_LENS_OVERLAY)); // Enter into fullscreen mode. - FullscreenController* fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); content::WebContents* tab_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); fullscreen_controller->EnterFullscreenModeForTab(
diff --git a/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc b/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc index 45ca62e..753f0a0 100644 --- a/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc +++ b/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc
@@ -3847,7 +3847,7 @@ /*primary_content_type=*/lens::MimeType::kUnknown, /*pdf_current_page=*/std::nullopt, 0, base::TimeTicks::Now()); ASSERT_TRUE(full_image_response_future.Wait()); - ASSERT_FALSE(query_controller.last_cluster_info_request().has_value()); + ASSERT_TRUE(query_controller.last_cluster_info_request().has_value()); query_controller.SendRegionSearch( kTestTime, std::move(region), lens::REGION_SEARCH,
diff --git a/chrome/browser/ui/passwords/password_change_ui_controller.cc b/chrome/browser/ui/passwords/password_change_ui_controller.cc index 183eaff..54e30fbc 100644 --- a/chrome/browser/ui/passwords/password_change_ui_controller.cc +++ b/chrome/browser/ui/passwords/password_change_ui_controller.cc
@@ -26,9 +26,14 @@ #include "components/vector_icons/vector_icons.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/dialog_model.h" +#include "ui/gfx/geometry/insets.h" #include "ui/gfx/vector_icon_types.h" +#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/bubble/bubble_dialog_model_host.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" namespace { @@ -100,6 +105,26 @@ .Build(); } +// Creates a BubbleFrameView to be used as the non-client frame view for the +// toast widget. This frame view provides rounded corners and a custom +// background color. +std::unique_ptr<views::NonClientFrameView> CreateToastFrameView( + const gfx::Insets& content_margins, + views::Widget* widget) { + auto frame_view = + std::make_unique<views::BubbleFrameView>(gfx::Insets(), content_margins); + auto border = std::make_unique<views::BubbleBorder>( + views::BubbleBorder::Arrow::NONE, + views::BubbleBorder::Shadow::STANDARD_SHADOW); + const int corner_radius = ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_TOAST_BUBBLE_HEIGHT); + border->set_rounded_corners(gfx::RoundedCornersF(corner_radius)); + border->set_draw_border_stroke(false); + frame_view->SetBubbleBorder(std::move(border)); + frame_view->SetBackgroundColor(ui::kColorToastBackgroundProminent); + return frame_view; +} + // Creates dialog for `PasswordChangeDelegate::State::kOtpDetected`. std::unique_ptr<ui::DialogModel> CreateOtpDetectedDialog( base::OnceClosure accept_callback) { @@ -139,15 +164,10 @@ GetDialogOrToastConfiguration(state); if (std::holds_alternative<ToastOptions>(configuration)) { - if (toast_view_) { - CHECK(toast_delegate_); - toast_view_->UpdateLayout( - std::move(std::get<ToastOptions>(configuration))); - toast_delegate_->set_margins(toast_view_->CalculateMargins()); - toast_view_->GetWidget()->SetBounds( - toast_delegate_->GetDesiredWidgetBounds()); - return; - } + // Close the existing dialog before showing toast. This is needed in + // PasswordChangeToastBrowserTest.InvokeUi_Toast. + CloseDialogWidget(views::Widget::ClosedReason::kUnspecified); + CloseToastWidget(views::Widget::ClosedReason::kUnspecified); ShowToast(std::move(std::get<ToastOptions>(configuration))); return; } @@ -240,39 +260,40 @@ std::u16string title = options.text; auto toast_view = std::make_unique<PasswordChangeToast>(std::move(options)); toast_view_ = toast_view.get(); - auto params = std::make_unique<tabs::TabDialogManager::Params>(); - params->close_on_navigate = false; - params->close_on_detach = false; - params->disable_input = false; - toast_delegate_ = std::make_unique<views::DialogDelegate>(); - toast_delegate_->SetModalType(ui::mojom::ModalType::kChild); - toast_delegate_->SetOwnershipOfNewWidget( - views::Widget::InitParams::CLIENT_OWNS_WIDGET); - toast_delegate_->set_use_custom_frame(true); - toast_delegate_->SetShowCloseButton(false); - toast_delegate_->SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone)); - toast_delegate_->SetContentsView(std::move(toast_view)); - toast_delegate_->set_corner_radius( - ChromeLayoutProvider::Get()->GetDistanceMetric( - DISTANCE_TOAST_BUBBLE_HEIGHT)); - toast_delegate_->set_margins(toast_view_->CalculateMargins()); - toast_delegate_->SetAccessibleWindowRole(ax::mojom::Role::kAlert); - toast_delegate_->SetAccessibleTitle(title); - toast_delegate_->RegisterWidgetInitializedCallback(base::BindOnce( - [](views::DialogDelegate* delegate) { - views::BubbleFrameView* frame_view = delegate->GetBubbleFrameView(); - if (frame_view) { - frame_view->SetBackgroundColor(ui::kColorToastBackgroundProminent); - frame_view->bubble_border()->set_draw_border_stroke(false); - } - }, - base::Unretained(toast_delegate_.get()))); + auto toast_delegate = std::make_unique<views::WidgetDelegate>(); + toast_delegate->SetModalType(ui::mojom::ModalType::kChild); + toast_delegate->SetContentsView(std::move(toast_view)); + toast_delegate->SetAccessibleWindowRole(ax::mojom::Role::kAlert); + toast_delegate->SetAccessibleTitle(title); + toast_delegate->SetShowCloseButton(false); + toast_delegate->SetNonClientFrameViewFactory(base::BindRepeating( + &CreateToastFrameView, toast_view_->CalculateMargins())); + toast_delegate_ = std::move(toast_delegate); - toast_widget_ = - tab_interface_->GetTabFeatures() - ->tab_dialog_manager() - ->CreateAndShowDialog(toast_delegate_.get(), std::move(params)); + auto* tab_dialog_manager = + tab_interface_->GetTabFeatures()->tab_dialog_manager(); + auto widget = std::make_unique<views::Widget>(); + views::Widget::InitParams init_params( + views::Widget::InitParams::Ownership::CLIENT_OWNS_WIDGET); + init_params.delegate = toast_delegate_.get(); + // Use translucency to enable rounded corners. + init_params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + init_params.parent = tab_dialog_manager->GetHostWidget()->GetNativeView(); + // Disable the system shadow. BubbleFrameView will draw a custom shadow. + init_params.shadow_type = views::Widget::InitParams::ShadowType::kNone; + init_params.remove_standard_frame = true; + init_params.name = "PasswordChangeToast"; + widget->Init(std::move(init_params)); + + auto tab_dialog_params = std::make_unique<tabs::TabDialogManager::Params>(); + tab_dialog_params->close_on_navigate = false; + tab_dialog_params->close_on_detach = false; + tab_dialog_params->disable_input = false; + + tab_dialog_manager->ShowDialog(widget.get(), std::move(tab_dialog_params)); + + toast_widget_ = std::move(widget); toast_widget_->MakeCloseSynchronous( base::BindOnce(&PasswordChangeUIController::CloseToastWidget, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ui/passwords/password_change_ui_controller.h b/chrome/browser/ui/passwords/password_change_ui_controller.h index 5befc6fa..2233cdeb 100644 --- a/chrome/browser/ui/passwords/password_change_ui_controller.h +++ b/chrome/browser/ui/passwords/password_change_ui_controller.h
@@ -19,10 +19,6 @@ class DialogModel; } // namespace ui -namespace views { -class DialogDelegate; -} // namespace views - // Responsible for creating and displaying appropriate views based on the // current state of the password change flow. class PasswordChangeUIController { @@ -68,8 +64,8 @@ // View displaying the progress of password change. raw_ptr<PasswordChangeToast> toast_view_; - // Delegate for the `toast_view_`. - std::unique_ptr<views::DialogDelegate> toast_delegate_; + // Delegate for the `toast_widget_`. + std::unique_ptr<views::WidgetDelegate> toast_delegate_; // Widget containing the currently open toast, if any. std::unique_ptr<views::Widget> toast_widget_;
diff --git a/chrome/browser/ui/tabs/alert/tab_alert_icon.cc b/chrome/browser/ui/tabs/alert/tab_alert_icon.cc index acd260f9..284160b 100644 --- a/chrome/browser/ui/tabs/alert/tab_alert_icon.cc +++ b/chrome/browser/ui/tabs/alert/tab_alert_icon.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/tabs/alert/tab_alert_icon.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tabs/alert/tab_alert.h" #include "chrome/common/chrome_features.h" @@ -17,6 +18,53 @@ namespace tabs { +ui::ColorId GetAlertIndicatorColor(TabAlert state, + bool is_tab_active, + bool is_frame_active) { + int group = 0; + switch (state) { + case tabs::TabAlert::MEDIA_RECORDING: + case tabs::TabAlert::AUDIO_RECORDING: + case tabs::TabAlert::VIDEO_RECORDING: + case tabs::TabAlert::DESKTOP_CAPTURING: + group = 0; + break; + case tabs::TabAlert::TAB_CAPTURING: + case tabs::TabAlert::PIP_PLAYING: + case tabs::TabAlert::GLIC_ACCESSING: + case tabs::TabAlert::GLIC_SHARING: + group = 1; + break; + case tabs::TabAlert::AUDIO_PLAYING: + case tabs::TabAlert::AUDIO_MUTING: + case tabs::TabAlert::BLUETOOTH_CONNECTED: + case tabs::TabAlert::BLUETOOTH_SCAN_ACTIVE: + case tabs::TabAlert::USB_CONNECTED: + case tabs::TabAlert::HID_CONNECTED: + case tabs::TabAlert::SERIAL_CONNECTED: + case tabs::TabAlert::VR_PRESENTING_IN_HEADSET: + group = 2; + break; + default: + NOTREACHED() << "Unknown tab alert state"; + } + + static constexpr std::array<std::array<std::array<ui::ColorId, 2>, 2>, 3> + color_ids{{{{{kColorTabAlertMediaRecordingInactiveFrameInactive, + kColorTabAlertMediaRecordingInactiveFrameActive}, + {kColorTabAlertMediaRecordingActiveFrameInactive, + kColorTabAlertMediaRecordingActiveFrameActive}}}, + {{{kColorTabAlertPipPlayingInactiveFrameInactive, + kColorTabAlertPipPlayingInactiveFrameActive}, + {kColorTabAlertPipPlayingActiveFrameInactive, + kColorTabAlertPipPlayingActiveFrameActive}}}, + {{{kColorTabAlertAudioPlayingInactiveFrameInactive, + kColorTabAlertAudioPlayingInactiveFrameActive}, + {kColorTabAlertAudioPlayingActiveFrameInactive, + kColorTabAlertAudioPlayingActiveFrameActive}}}}}; + return color_ids[group][is_tab_active][is_frame_active]; +} + const gfx::VectorIcon& GetAlertIcon(TabAlert alert_state) { switch (alert_state) { case TabAlert::AUDIO_PLAYING:
diff --git a/chrome/browser/ui/tabs/alert/tab_alert_icon.h b/chrome/browser/ui/tabs/alert/tab_alert_icon.h index 3472494..3b56c58 100644 --- a/chrome/browser/ui/tabs/alert/tab_alert_icon.h +++ b/chrome/browser/ui/tabs/alert/tab_alert_icon.h
@@ -16,6 +16,11 @@ enum class TabAlert; +// Returns the corresponding color for the given alert. +ui::ColorId GetAlertIndicatorColor(TabAlert state, + bool is_tab_active, + bool is_frame_active); + // Returns the corresponding icon for the given alert. const gfx::VectorIcon& GetAlertIcon(TabAlert alert_state);
diff --git a/chrome/browser/ui/tabs/public/tab_dialog_manager.h b/chrome/browser/ui/tabs/public/tab_dialog_manager.h index 8efd4c7..4e45da2 100644 --- a/chrome/browser/ui/tabs/public/tab_dialog_manager.h +++ b/chrome/browser/ui/tabs/public/tab_dialog_manager.h
@@ -82,6 +82,10 @@ // * From CloseDialog(), right before calling Close() on the widget. void WidgetDestroyed(views::Widget* widget); + // Returns the widget associated with the browser window. This widget is used + // as the parent for tab-scoped widgets. + views::Widget* GetHostWidget() const; + private: // Overridden from content::WebContentObserver: void DidFinishNavigation(
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/instant_message_queue_processor.cc b/chrome/browser/ui/tabs/saved_tab_groups/instant_message_queue_processor.cc index 49cd3d6..93da70f 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/instant_message_queue_processor.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/instant_message_queue_processor.cc
@@ -274,10 +274,6 @@ params.body_string_override = queued_message.message.localized_message; return params; } - case CollaborationEvent::VERSION_OUT_OF_DATE: { - // TODO(crbug.com/420680426): Implement version UI. - return std::nullopt; - } default: return std::nullopt; }
diff --git a/chrome/browser/ui/tabs/tab_dialog_manager.cc b/chrome/browser/ui/tabs/tab_dialog_manager.cc index f42166d..15ea8d2 100644 --- a/chrome/browser/ui/tabs/tab_dialog_manager.cc +++ b/chrome/browser/ui/tabs/tab_dialog_manager.cc
@@ -261,8 +261,7 @@ std::unique_ptr<views::Widget> TabDialogManager::CreateTabScopedDialog( views::DialogDelegate* delegate) { DCHECK_EQ(ui::mojom::ModalType::kChild, delegate->GetModalType()); - views::Widget* host = - tab_interface_->GetBrowserWindowInterface()->TopContainer()->GetWidget(); + views::Widget* host = GetHostWidget(); CHECK(host); return base::WrapUnique(views::DialogDelegate::CreateDialogWidget( delegate, gfx::NativeWindow(), host->GetNativeView())); @@ -334,6 +333,12 @@ ->SetWebContentsBlocked(tab_interface_->GetContents(), /*blocked=*/false); } +views::Widget* TabDialogManager::GetHostWidget() const { + return tab_interface_->GetBrowserWindowInterface() + ->TopContainer() + ->GetWidget(); +} + void TabDialogManager::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (!widget_) { @@ -376,8 +381,7 @@ widget_.get()); // Check if the tab was detached and dragged to a new browser window. This // ensures the widget is properly reparented. - auto* parent_widget = - tab_interface->GetBrowserWindowInterface()->TopContainer()->GetWidget(); + auto* parent_widget = GetHostWidget(); if (parent_widget != widget_->parent()) { widget_->Reparent(parent_widget); }
diff --git a/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc b/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc index d539ce0..de4e8b68 100644 --- a/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc +++ b/chrome/browser/ui/toasts/toast_controller_interactive_ui_test.cc
@@ -509,7 +509,10 @@ ToastRendersOverWebContents) { #if BUILDFLAG(IS_MAC) FullscreenController* const fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); fullscreen_controller->set_is_tab_fullscreen_for_testing(true); #else ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true});
diff --git a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc index f04bbe5..4e26149 100644 --- a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc +++ b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar/app_menu_model.h" @@ -101,8 +102,9 @@ [](std::unique_ptr<ui_test_utils::FullscreenWaiter>& waiter, bool is_fullscreen, Browser* browser, views::View* browser_view) { - auto* fullscreen_controller = - browser->exclusive_access_manager()->fullscreen_controller(); + auto* fullscreen_controller = browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); // Wait for fullscreen transition complete. // Fullscreen transition is an async process on Mac, which
diff --git a/chrome/browser/ui/views/external_protocol_handler_ash.cc b/chrome/browser/ui/views/external_protocol_handler_ash.cc index f409b8a..04be034 100644 --- a/chrome/browser/ui/views/external_protocol_handler_ash.cc +++ b/chrome/browser/ui/views/external_protocol_handler_ash.cc
@@ -5,22 +5,28 @@ #include <string> #include "ash/constants/ash_features.h" +#include "base/containers/to_vector.h" #include "base/memory/raw_ptr.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.h" #include "chrome/browser/ash/guest_os/guest_os_external_protocol_handler.h" #include "chrome/browser/chromeos/arc/arc_external_protocol_dialog.h" #include "chrome/browser/external_protocol/external_protocol_handler.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/views/external_protocol_dialog.h" +#include "chrome/browser/web_applications/app_service/publisher_helper.h" #include "chrome/grit/branded_strings.h" #include "chrome/grit/generated_resources.h" #include "chromeos/ash/components/browser_context_helper/browser_context_types.h" +#include "chromeos/constants/chromeos_features.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/weak_document_ptr.h" #include "content/public/browser/web_contents.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/mojom/dialog_button.mojom.h" @@ -82,6 +88,8 @@ base::TimeTicks creation_time_; }; +namespace { + void OnArcHandled(const GURL& url, const std::optional<url::Origin>& initiating_origin, content::WeakDocumentPtr initiator_document, @@ -117,6 +125,51 @@ } } +std::string GetAppName(apps::AppServiceProxy* proxy, + const std::string& app_id) { + std::optional<std::string> app_name; + proxy->AppRegistryCache().ForOneApp( + app_id, + [&](const apps::AppUpdate& update) { app_name = update.ShortName(); }); + CHECK(app_name); + return *app_name; +} + +void HandleWebAppManifestProtocolHandler( + Profile* profile, + WebContents* web_contents, + const GURL& url, + const std::vector<std::string>& app_ids, + const std::optional<url::Origin>& initiating_origin, + content::WeakDocumentPtr initiator_document) { + CHECK(!app_ids.empty()); + CHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + if (app_ids.size() > 1) { + // TODO(crbug.com/422422887): Figure out how to disambiguate conflicting + // protocol handlers; for now, pick the first one in the list. + static constexpr std::string_view kConfictingProtocolHandlersWarning = + "There's more than one web application handling %s links : [%s]; " + "ChromeOS currently doesn't support disambiguating multiple handlers."; + if (content::RenderFrameHost* rfh = + initiator_document.AsRenderFrameHostIfValid()) { + std::vector<std::string> app_names = base::ToVector( + app_ids, + [&](const auto& app_id) { return GetAppName(proxy, app_id); }); + rfh->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + base::StringPrintf(kConfictingProtocolHandlersWarning, url.scheme(), + base::JoinString(app_names, ","))); + } + } + + new ExternalProtocolDialog(web_contents, url, + base::UTF8ToUTF16(GetAppName(proxy, app_ids[0])), + initiating_origin, std::move(initiator_document)); +} + +} // namespace + /////////////////////////////////////////////////////////////////////////////// // ExternalProtocolHandler @@ -136,8 +189,18 @@ return; } - // First, check if ARC version of the dialog is available and run ARC version - // when possible. + auto* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + if (std::vector<std::string> app_ids = + web_app::GetWebAppIdsForProtocolUrl(profile, url); + !app_ids.empty()) { + HandleWebAppManifestProtocolHandler(profile, web_contents, url, app_ids, + initiating_origin, initiator_document); + return; + } + + // Check if ARC version of the dialog is available and run ARC + // version when possible. arc::RunArcExternalProtocolDialog( url, initiating_origin, web_contents->GetWeakPtr(), page_transition, has_user_gesture, is_in_fenced_frame_tree,
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_win.cc b/chrome/browser/ui/views/frame/browser_frame_view_win.cc index c3e640c..152ca20 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_win.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_win.cc
@@ -222,7 +222,7 @@ SkColor BrowserFrameViewWin::GetCaptionColor( BrowserFrameActiveState active_state) const { - return GetColorProvider()->GetColor(ShouldPaintAsActive(active_state) + return GetColorProvider()->GetColor(ShouldPaintAsActiveForState(active_state) ? kColorCaptionForegroundActive : kColorCaptionForegroundInactive); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index a36cbc59e..fdab418 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -9,9 +9,6 @@ #include "build/buildflag.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/profiles/avatar_menu.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/themes/custom_theme_supplier.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/color/chrome_color_id.h" @@ -50,23 +47,9 @@ : frame_(frame), browser_view_(browser_view) { DCHECK(frame_); DCHECK(browser_view_); - - // The profile manager may by null in tests. - if (g_browser_process->profile_manager()) { - g_browser_process->profile_manager() - ->GetProfileAttributesStorage() - .AddObserver(this); - } } -BrowserNonClientFrameView::~BrowserNonClientFrameView() { - // The profile manager may by null in tests. - if (g_browser_process->profile_manager()) { - g_browser_process->profile_manager() - ->GetProfileAttributesStorage() - .RemoveObserver(this); - } -} +BrowserNonClientFrameView::~BrowserNonClientFrameView() = default; void BrowserNonClientFrameView::OnBrowserViewInitViewsComplete() { UpdateMinimumSize(); @@ -104,7 +87,7 @@ TabStrip* const tab_strip = browser_view_->tabstrip(); - const bool active = ShouldPaintAsActive(active_state); + const bool active = ShouldPaintAsActiveForState(active_state); const std::optional<int> bg_id = tab_strip->GetCustomBackgroundId(active_state); if (bg_id.has_value()) { @@ -139,7 +122,7 @@ // color. return TabStyle::Get()->GetTabBackgroundColor( TabStyle::TabSelectionState::kInactive, - /*hovered=*/false, ShouldPaintAsActive(active_state), + /*hovered=*/false, ShouldPaintAsActiveForState(active_state), *GetColorProvider()) != GetFrameColor(active_state); } @@ -156,14 +139,14 @@ SkColor BrowserNonClientFrameView::GetCaptionColor( BrowserFrameActiveState active_state) const { - return GetColorProvider()->GetColor(ShouldPaintAsActive(active_state) + return GetColorProvider()->GetColor(ShouldPaintAsActiveForState(active_state) ? kColorFrameCaptionActive : kColorFrameCaptionInactive); } SkColor BrowserNonClientFrameView::GetFrameColor( BrowserFrameActiveState active_state) const { - return GetColorProvider()->GetColor(ShouldPaintAsActive(active_state) + return GetColorProvider()->GetColor(ShouldPaintAsActiveForState(active_state) ? ui::kColorFrameActive : ui::kColorFrameInactive); } @@ -172,7 +155,7 @@ BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); const bool incognito = browser_view_->GetIncognito(); - const bool active = ShouldPaintAsActive(active_state); + const bool active = ShouldPaintAsActiveForState(active_state); const int active_id = incognito ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; const int inactive_id = incognito @@ -195,17 +178,6 @@ void BrowserNonClientFrameView::UpdateMinimumSize() {} -void BrowserNonClientFrameView::VisibilityChanged(views::View* starting_from, - bool is_visible) { - // UpdateTaskbarDecoration() calls DrawTaskbarDecoration(), but that does - // nothing if the window is not visible. So even if we've already gotten the - // up-to-date decoration, we need to run the update procedure again here when - // the window becomes visible. - if (is_visible) { - OnProfileAvatarChanged(base::FilePath()); - } -} - gfx::Insets BrowserNonClientFrameView::RestoredMirroredFrameBorderInsets() const { NOTREACHED(); @@ -232,17 +204,17 @@ SchedulePaint(); } -bool BrowserNonClientFrameView::ShouldPaintAsActive( +bool BrowserNonClientFrameView::ShouldPaintAsActiveForState( BrowserFrameActiveState active_state) const { return (active_state == BrowserFrameActiveState::kUseCurrent) - ? ShouldPaintAsActive() + ? NonClientFrameView::ShouldPaintAsActive() : (active_state == BrowserFrameActiveState::kActive); } gfx::ImageSkia BrowserNonClientFrameView::GetFrameImage( BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); - const int frame_image_id = ShouldPaintAsActive(active_state) + const int frame_image_id = ShouldPaintAsActiveForState(active_state) ? IDR_THEME_FRAME : IDR_THEME_FRAME_INACTIVE; return (tp->HasCustomImage(frame_image_id) || @@ -258,7 +230,7 @@ } const ui::ThemeProvider* tp = GetThemeProvider(); - const int frame_overlay_image_id = ShouldPaintAsActive(active_state) + const int frame_overlay_image_id = ShouldPaintAsActiveForState(active_state) ? IDR_THEME_FRAME_OVERLAY : IDR_THEME_FRAME_OVERLAY_INACTIVE; return tp->HasCustomImage(frame_overlay_image_id) @@ -266,33 +238,6 @@ : gfx::ImageSkia(); } -void BrowserNonClientFrameView::OnProfileAdded( - const base::FilePath& profile_path) { - OnProfileAvatarChanged(profile_path); -} - -void BrowserNonClientFrameView::OnProfileWasRemoved( - const base::FilePath& profile_path, - const std::u16string& profile_name) { - OnProfileAvatarChanged(profile_path); -} - -void BrowserNonClientFrameView::OnProfileAvatarChanged( - const base::FilePath& profile_path) { -#if BUILDFLAG(IS_WIN) - taskbar::UpdateTaskbarDecoration(browser_view()->browser()->profile(), - frame_->GetNativeWindow()); -#endif -} - -void BrowserNonClientFrameView::OnProfileHighResAvatarLoaded( - const base::FilePath& profile_path) { -#if BUILDFLAG(IS_WIN) - taskbar::UpdateTaskbarDecoration(browser_view()->browser()->profile(), - frame_->GetNativeWindow()); -#endif -} - #if BUILDFLAG(IS_WIN) // Sending the WM_NCPOINTERDOWN, WM_NCPOINTERUPDATE, and WM_NCPOINTERUP to the // default window proc does not bring up the system menu on long press, so we
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index 2238e76..09a9110 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -7,30 +7,44 @@ #include "base/memory/raw_ptr.h" #include "build/build_config.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/ui/views/frame/browser_frame.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/window/non_client_view.h" class BrowserView; -// Type used for functions whose return values depend on the active state of -// the frame. +// This enum is used for functions who rely on the state of the browser to alter +// the appearance of the window frame. enum class BrowserFrameActiveState { - kUseCurrent, // Use current frame active state. - kActive, // Treat frame as active regardless of current state. - kInactive, // Treat frame as inactive regardless of current state. + // Use the window's actual current active/inactive state. + kUseCurrent, + // Force the frame to be treated as active, regardless of the current state. + // Note: Only used on ChromeOS. + kActive, + // Force the frame to be treated as inactive, regardless of the current sate. + // Note: Only used on ChromeOS. + kInactive, }; -// A specialization of the NonClientFrameView object that provides additional -// Browser-specific methods. -class BrowserNonClientFrameView : public views::NonClientFrameView, - public ProfileAttributesStorage::Observer { +// BrowserNonClientFrameView is an abstract base class that defines the +// interface for the part of a browser window that is not the "client area" +// (where the web content is displayed). This includes the title bar, window +// borders, and caption buttons (minimize, maximize, close). +// +// This class is responsible for: +// - Laying out major UI components like the tab strip. +// - Painting the window frame, taking into account the browser theme. +// - Responding to window state changes (fullscreen, activation, maximization). +// +// Concrete implementations are provided for each platform (e.g., Windows, Mac, +// Linux) and are created by the factory function +// `chrome::CreateBrowserNonClientFrameView`. +class BrowserNonClientFrameView : public views::NonClientFrameView { METADATA_HEADER(BrowserNonClientFrameView, views::NonClientFrameView) public: - // The minimum total height users should have to use as a drag handle to move - // the window with. + // The minimum height of the region at the top of the frame that should be + // draggable to move the window. static constexpr int kMinimumDragHeight = 8; BrowserNonClientFrameView(BrowserFrame* frame, BrowserView* browser_view); @@ -42,115 +56,124 @@ BrowserView* browser_view() const { return browser_view_; } BrowserFrame* frame() const { return frame_; } - // Called when BrowserView creates all it's child views. + // Called after BrowserView has initialized its child views. This is a useful + // hook for performing final setup that depends on other child views, like + // the tabstrip or toolbar, being present. virtual void OnBrowserViewInitViewsComplete(); - // Called after the browser window is fullscreened or unfullscreened. + // Called when the browser window's fullscreen state changes. virtual void OnFullscreenStateChanged(); - // Returns whether the caption buttons are drawn at the leading edge (i.e. the - // left in LTR mode, or the right in RTL mode). + // Returns whether the caption buttons are drawn at the leading edge (e.g. on + // the left for LTR languages, such as on macOS). virtual bool CaptionButtonsOnLeadingEdge() const; - // Retrieves the bounds in non-client view coordinates within which the - // TabStrip should be laid out. + // Returns the bounds, in this view's coordinates, that the tab + // strip should occupy. virtual gfx::Rect GetBoundsForTabStripRegion( const gfx::Size& tabstrip_minimum_size) const = 0; - // Retrieves the maximum bounds in non-client view coordinates for the - // WebAppFrameToolbarView that contains Web App controls. + // Returns the maximum bounds, in this view's coordinates, for + // the WebAppFrameToolbarView, which contains controls for a web app. virtual gfx::Rect GetBoundsForWebAppFrameToolbar( const gfx::Size& toolbar_preferred_size) const = 0; // Lays out the window title for a web app within the given available space. - // Unlike the above GetBounds methods this is not just a method to return the - // bounds the title should occupy, since different implementations might also - // want to change other attributes of the title, such as alignment. + // This method doesn't just return bounds; it may also modify properties of + // the label itself, such as text alignment, based on the implementation. virtual void LayoutWebAppWindowTitle( const gfx::Rect& available_space, views::Label& window_title_label) const = 0; - // Returns the inset of the topmost view in the client view from the top of - // the non-client view. The topmost view depends on the window type. The - // topmost view is the tab strip for tabbed browser windows, the toolbar for - // popups, the web contents for app windows and varies for fullscreen windows. - // If |restored| is true, this is calculated as if the window was restored, - // regardless of its current state. + // Returns the inset from the top of the window to the top of the client + // view. For a tabbed browser, this is the space occupied by the tab strip. + // For popup windows, this is the toolbar. For app windows, this is the + // WebContents. Varies on fullscreen. If |restored| is true, this is + // calculated for the window's restored state, regardless of its current state + // (e.g., maximized or fullscreen). virtual int GetTopInset(bool restored) const = 0; // Updates the top UI state to be hidden or shown in fullscreen according to // the preference's state. Currently only used on Mac. virtual void UpdateFullscreenTopUI(); - // Returns whether the top UI should hide. + // Returns true if the top UI (tabstrip, toolbar) should be hidden because the + // browser is in fullscreen mode. virtual bool ShouldHideTopUIForFullscreen() const; // Returns whether the user is allowed to exit fullscreen on their own (some // special modes lock the user in fullscreen). virtual bool CanUserExitFullscreen() const; - // Determines whether the top frame is condensed vertically, as when the - // window is maximized. If true, the top frame is just the height of a tab, + // Determines whether the top of the frame is "condensed" (i.e., has less + // vertical space). This is typically true when the window is maximized or + // fullscreen. If true, the top frame is just the height of a tab, // rather than having extra vertical space above the tabs. virtual bool IsFrameCondensed() const; - // Returns whether the shapes of background tabs are visible against the - // frame, given an active state of |active|. + // Determines if background tab shapes have a distinct appearance from the + // frame background. This is true if the theme uses a custom tab background + // image or if the calculated color for background tabs differs from the frame + // color. virtual bool HasVisibleBackgroundTabShapes( BrowserFrameActiveState active_state) const; - // Returns whether the shapes of background tabs are visible against the frame - // for either active or inactive windows. + // Returns true if background tabs are ever visibly distinct from the frame, + // in either the active or inactive state. bool EverHasVisibleBackgroundTabShapes() const; - // Returns whether tab strokes can be drawn. + // Returns true if strokes (outlines/separators) should be drawn around tabs. + // This is generally true, but false for some web apps that don't have a tab + // strip. virtual bool CanDrawStrokes() const; - // Returns the color to use for text, caption buttons, and other title bar - // elements. + // Returns the color that should be used for text and icons in the title bar + // (e.g., the window title and caption button icons). virtual SkColor GetCaptionColor(BrowserFrameActiveState active_state) const; - // Returns the color of the browser frame, which is also the color of the - // tabstrip background. + // Returns the primary background color of the browser frame. This is also the + // color used for the tab strip background unless overridden by a theme. virtual SkColor GetFrameColor(BrowserFrameActiveState active_state) const; - // For non-transparent windows, returns the background tab image resource ID - // if the image has been customized, directly or indirectly, by the theme. + // Returns the resource ID for a custom background image if the active theme + // provides one for the frame. This checks for images for the given active + // state and also considers theme-related fallbacks (e.g., an inactive image + // falling back to an active one). std::optional<int> GetCustomBackgroundId( BrowserFrameActiveState active_state) const; - // Updates the throbber. + // Updates the the loading animation (throbber) for the window icon in the + // frame. Mainly used by special browsers such as PWAs. virtual void UpdateThrobber(bool running) = 0; - // Provided for platform-specific updates of minimum window size. + // Signals that the frame's minimum size may have changed. This prompts the + // widget to update its size constraints by re-querying `GetMinimumSize()`. + // This is typically called when child views (e.g. tab strip, toolbar, + // bookmarks bar) change visibility.The window manager is notified of this + // change via GetWidget()->OnSizeConstraintsChanged(). virtual void UpdateMinimumSize(); - // Updates the state of the title bar when window controls overlay is enabled - // or disabled. + // Called when the Window Controls Overlay state changes, allowing the frame + // to update the state of the caption buttons accordingly. virtual void WindowControlsOverlayEnabledChanged() {} - // views::NonClientFrameView: - using views::NonClientFrameView::ShouldPaintAsActive; - void VisibilityChanged(views::View* starting_from, bool is_visible) override; - // Returns the insets from the edge of the native window to the client view in // DIPs. The value is left-to-right even on RTL locales. That is, - // insets.left() will be on the left in screen coordinates. + // insets.left() will be on the left in screen coordinates. Subclasses must + // implement this. virtual gfx::Insets RestoredMirroredFrameBorderInsets() const; // Returns the insets from the client view to the input region. The returned // insets will be negative, such that view_rect.Inset(GetInputInsets()) will - // be the input region. + // be the input region. Subclasses must implement this. virtual gfx::Insets GetInputInsets() const; - // Gets the rounded-rect that will be used to clip the window frame when - // drawing. The region will be as if the window was restored, and will be in - // view coordinates. + // Gets the rounded-rect clipping region for the window frame when it is + // in its restored (non-maximized) state. Subclasses must implement this. virtual SkRRect GetRestoredClipRegion() const; - // Returns the height of the top frame. This value will be 0 if the - // compositor doesn't support translucency, if the top frame is not - // translucent, or if the window is in full screen mode. + // Returns the height of the translucent area at the top of the frame. Returns + // 0 if the frame is opaque (not transparent) or in fullscreen. virtual int GetTranslucentTopAreaHeight() const; #if BUILDFLAG(IS_MAC) @@ -162,28 +185,22 @@ virtual void SetFrameBounds(const gfx::Rect& bounds); protected: - // Called when |frame_|'s "paint as active" state has changed. + // Called when `frame_`'s "paint as active" state has changed. virtual void PaintAsActiveChanged(); - // Converts an ActiveState to a bool representing whether the frame should be - // treated as active. - bool ShouldPaintAsActive(BrowserFrameActiveState active_state) const; + // Helper function to determine if we should treat the frame as the active + // state. + bool ShouldPaintAsActiveForState(BrowserFrameActiveState active_state) const; - // Compute aspects of the frame needed to paint the frame background. + // Returns a themed image for the frame background, if one exists. gfx::ImageSkia GetFrameImage(BrowserFrameActiveState active_state = BrowserFrameActiveState::kUseCurrent) const; + + // Returns a themed image for the frame overlay, if one exists. gfx::ImageSkia GetFrameOverlayImage( BrowserFrameActiveState active_state = BrowserFrameActiveState::kUseCurrent) const; - // ProfileAttributesStorage::Observer: - void OnProfileAdded(const base::FilePath& profile_path) override; - void OnProfileWasRemoved(const base::FilePath& profile_path, - const std::u16string& profile_name) override; - void OnProfileAvatarChanged(const base::FilePath& profile_path) override; - void OnProfileHighResAvatarLoaded( - const base::FilePath& profile_path) override; - private: #if BUILDFLAG(IS_WIN) // ui::EventHandler: @@ -193,12 +210,14 @@ int GetSystemMenuY() const override; #endif // BUILDFLAG(IS_WIN) - // The frame that hosts this view. + // The BrowserFrame that owns this view. const raw_ptr<BrowserFrame, DanglingUntriaged> frame_; - // The BrowserView hosted within this View. + // The BrowserView hosted within `frame_`. const raw_ptr<BrowserView, DanglingUntriaged> browser_view_; + // Subscription to receive notifications when the frame's PaintAsActive state + // changes. base::CallbackListSubscription paint_as_active_subscription_ = frame_->RegisterPaintAsActiveChangedCallback( base::BindRepeating(&BrowserNonClientFrameView::PaintAsActiveChanged, @@ -207,7 +226,9 @@ namespace chrome { -// Provided by a browser_non_client_frame_view_factory_*.cc implementation +// Factory function for creating a BrowserNonClientFrameView. Platform specific +// implementations should define this in their respective +// browser_non_client_view_factor_*.cc files. std::unique_ptr<BrowserNonClientFrameView> CreateBrowserNonClientFrameView( BrowserFrame* frame, BrowserView* browser_view);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc index 4abfd1c..3e2247ec 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.cc
@@ -16,13 +16,17 @@ #include "build/build_config.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" #include "chrome/browser/ui/ash/session/session_util.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -129,6 +133,44 @@ } // namespace +class BrowserNonClientFrameViewChromeOS::ProfileChangeObserver + : public ProfileAttributesStorage::Observer { + public: + explicit ProfileChangeObserver(BrowserNonClientFrameViewChromeOS& frame) + : frame_(frame) { + if (g_browser_process->profile_manager()) { + profile_observation_.Observe( + &g_browser_process->profile_manager()->GetProfileAttributesStorage()); + } else { + CHECK_IS_TEST(); + } + } + + ~ProfileChangeObserver() override = default; + + // ProfileAttributesStorage::Observer: + void OnProfileAdded(const base::FilePath& profile_path) override { + frame_->UpdateProfileIcons(); + } + void OnProfileWasRemoved(const base::FilePath& profile_path, + const std::u16string& profile_name) override { + frame_->UpdateProfileIcons(); + } + void OnProfileAvatarChanged(const base::FilePath& profile_path) override { + frame_->UpdateProfileIcons(); + } + void OnProfileHighResAvatarLoaded( + const base::FilePath& profile_path) override { + frame_->UpdateProfileIcons(); + } + + private: + raw_ref<BrowserNonClientFrameViewChromeOS> frame_; + base::ScopedObservation<ProfileAttributesStorage, + ProfileAttributesStorage::Observer> + profile_observation_{this}; +}; + BrowserNonClientFrameViewChromeOS::BrowserNonClientFrameViewChromeOS( BrowserFrame* frame, BrowserView* browser_view) @@ -306,7 +348,7 @@ const SkColor active_caption_color = views::FrameCaptionButton::GetButtonColor(frame_color); - if (ShouldPaintAsActive(active_state)) { + if (ShouldPaintAsActiveForState(active_state)) { return active_caption_color; } @@ -643,7 +685,7 @@ ImmersiveModeController* immersive_mode_controller = browser_view()->immersive_mode_controller(); ExclusiveAccessManager* exclusive_access_manager = - browser_view()->browser()->exclusive_access_manager(); + browser_view()->browser()->GetFeatures().exclusive_access_manager(); const bool was_immersive = immersive_mode_controller->IsEnabled(); const bool was_fullscreen = @@ -841,12 +883,6 @@ } } -void BrowserNonClientFrameViewChromeOS::OnProfileAvatarChanged( - const base::FilePath& profile_path) { - BrowserNonClientFrameView::OnProfileAvatarChanged(profile_path); - UpdateProfileIcons(); -} - void BrowserNonClientFrameViewChromeOS::AddedToWidget() { if (highlight_border_overlay_ || !GetWidget()->GetNativeWindow()->GetProperty(
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h index feeb74bf..9893271 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_chromeos.h
@@ -134,13 +134,13 @@ protected: // BrowserNonClientFrameView: void PaintAsActiveChanged() override; - void OnProfileAvatarChanged(const base::FilePath& profile_path) override; void AddedToWidget() override; private: friend class BrowserNonClientFrameViewChromeOSTestApi; FRIEND_TEST_ALL_PREFIXES(ImmersiveModeBrowserViewTestNoWebUiTabStrip, ImmersiveFullscreen); + class ProfileChangeObserver; // App is a PWA and has borderless in its manifest. This doesn't yet mean // that the `window-management` permission has been granted and borderless
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index cc00779f..deda6e0 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -6321,7 +6321,7 @@ /////////////////////////////////////////////////////////////////////////////// // BrowserView, ExclusiveAccessBubbleViewsContext implementation: ExclusiveAccessManager* BrowserView::GetExclusiveAccessManager() { - return browser_->exclusive_access_manager(); + return browser_->GetFeatures().exclusive_access_manager(); } ui::AcceleratorProvider* BrowserView::GetAcceleratorProvider() {
diff --git a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc index ed5d6c5a..bde51f0 100644 --- a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
@@ -7,6 +7,7 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -170,8 +171,10 @@ chrome::IsCommandEnabled(browser(), IDC_SHOW_BOOKMARK_BAR)); // Enter into tab fullscreen mode from browser fullscreen mode. - FullscreenController* controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); controller->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame()); @@ -188,7 +191,8 @@ blink::WebInputEvent::Type::kKeyDown, blink::WebInputEvent::kNoModifiers, blink::WebInputEvent::GetStaticTimeStampForTests()); event.windows_key_code = ui::VKEY_ESCAPE; - browser()->exclusive_access_manager()->HandleUserKeyEvent(event); + browser()->GetFeatures().exclusive_access_manager()->HandleUserKeyEvent( + event); EXPECT_TRUE(browser_view->IsFullscreen()); EXPECT_EQ(top_view_in_browser_fullscreen, browser_view->GetTabStripVisible()); // This makes sure that the layout was updated accordingly. @@ -213,8 +217,10 @@ EXPECT_TRUE(browser_view->GetTabStripVisible()); // Enter into tab fullscreen mode. - FullscreenController* controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); controller->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame()); @@ -248,8 +254,10 @@ EXPECT_TRUE(browser_view->IsInSplitView()); // Enter into tab fullscreen mode. - FullscreenController* controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); controller->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame()); @@ -545,28 +553,38 @@ IN_PROC_BROWSER_TEST_F(BrowserViewLockedFullscreenTestChromeOS, ShowExclusiveAccessBubbleWhenNotLocked) { PinWindow(browser()->window()->GetNativeWindow(), /*trusted=*/false); - browser()->exclusive_access_manager()->context()->UpdateExclusiveAccessBubble( - { - .origin = url::Origin::Create(GURL( - "http://www.example.com")), // Should be non-empty to show bubble - .type = ExclusiveAccessBubbleType:: - EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, - .force_update = true, - }, - base::NullCallback()); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->UpdateExclusiveAccessBubble( + { + .origin = url::Origin::Create( + GURL("http://www.example.com")), // Should be non-empty to + // show bubble + .type = ExclusiveAccessBubbleType:: + EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, + .force_update = true, + }, + base::NullCallback()); EXPECT_TRUE(browser_view()->IsExclusiveAccessBubbleDisplayed()); } IN_PROC_BROWSER_TEST_F(BrowserViewLockedFullscreenTestChromeOS, HideExclusiveAccessBubbleWhenLocked) { PinWindow(browser()->window()->GetNativeWindow(), /*trusted=*/true); - browser()->exclusive_access_manager()->context()->UpdateExclusiveAccessBubble( - {.origin = url::Origin::Create(GURL( - "http://www.example.com")), // Should be non-empty to show bubble - .type = ExclusiveAccessBubbleType:: - EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, - .force_update = true}, - base::NullCallback()); + browser() + ->GetFeatures() + .exclusive_access_manager() + ->context() + ->UpdateExclusiveAccessBubble( + {.origin = url::Origin::Create( + GURL("http://www.example.com")), // Should be non-empty to show + // bubble + .type = ExclusiveAccessBubbleType:: + EXCLUSIVE_ACCESS_BUBBLE_TYPE_FULLSCREEN_EXIT_INSTRUCTION, + .force_update = true}, + base::NullCallback()); EXPECT_FALSE(browser_view()->IsExclusiveAccessBubbleDisplayed()); }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc index 784124f..2787b14 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
@@ -8,6 +8,7 @@ #include "build/buildflag.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" @@ -80,7 +81,8 @@ if (!fullscreen_observer_.IsObserving()) { fullscreen_observer_.Observe(browser_view_->browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller()); } @@ -279,7 +281,8 @@ // Auto hide the shelf in immersive browser fullscreen. bool in_tab_fullscreen = browser_view_->browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsWindowFullscreenForTabOrPending(); browser_view_->GetNativeWindow()->SetProperty(
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm b/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm index b220d19..35de58fc 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac_interactive_uitest.mm
@@ -10,6 +10,7 @@ #import "base/mac/mac_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -155,8 +156,10 @@ EXPECT_EQ(GetMovedContentViewForWidget(overlay_widget), nullptr); ui_test_utils::ToggleFullscreenModeAndWait(browser()); - FullscreenController* fullscreen_controller = - browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); EXPECT_TRUE(fullscreen_controller->IsFullscreenForBrowser()); EXPECT_EQ(GetMovedContentViewForWidget(overlay_widget),
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_mini_toolbar.cc b/chrome/browser/ui/views/frame/multi_contents_view_mini_toolbar.cc index 3747c01a..4eded49 100644 --- a/chrome/browser/ui/views/frame/multi_contents_view_mini_toolbar.cc +++ b/chrome/browser/ui/views/frame/multi_contents_view_mini_toolbar.cc
@@ -55,34 +55,6 @@ return web_contents ? tabs::TabInterface::GetFromContents(web_contents) : nullptr; } - -ui::ColorId GetAlertStatusColor(tabs::TabAlert alert, - const ui::ColorProvider* color_provider) { - if (color_provider) { - switch (alert) { - case tabs::TabAlert::MEDIA_RECORDING: - case tabs::TabAlert::AUDIO_RECORDING: - case tabs::TabAlert::VIDEO_RECORDING: - case tabs::TabAlert::DESKTOP_CAPTURING: - return kColorTabAlertMediaRecordingActiveFrameActive; - case tabs::TabAlert::TAB_CAPTURING: - case tabs::TabAlert::PIP_PLAYING: - case tabs::TabAlert::GLIC_ACCESSING: - case tabs::TabAlert::GLIC_SHARING: - return kColorTabAlertPipPlayingActiveFrameActive; - case tabs::TabAlert::AUDIO_PLAYING: - case tabs::TabAlert::AUDIO_MUTING: - case tabs::TabAlert::BLUETOOTH_CONNECTED: - case tabs::TabAlert::BLUETOOTH_SCAN_ACTIVE: - case tabs::TabAlert::USB_CONNECTED: - case tabs::TabAlert::HID_CONNECTED: - case tabs::TabAlert::SERIAL_CONNECTED: - case tabs::TabAlert::VR_PRESENTING_IN_HEADSET: - return kColorTabAlertAudioPlayingActiveFrameActive; - } - } - return gfx::kPlaceholderColor; -} } // namespace MultiContentsViewMiniToolbar::MultiContentsViewMiniToolbar( @@ -227,6 +199,7 @@ OnAlertStatusIndicatorChanged(tab_alert_controller->GetAlertToShow()); } } + SkPath MultiContentsViewMiniToolbar::GetPath(bool border_stroke_only) const { const float corner_radius = kMiniToolbarOutlineCornerRadius; const gfx::Rect local_bounds = GetLocalBounds(); @@ -273,8 +246,9 @@ void MultiContentsViewMiniToolbar::OnAlertStatusIndicatorChanged( std::optional<tabs::TabAlert> new_alert) { if (new_alert.has_value()) { - ui::ColorId color = - GetAlertStatusColor(new_alert.value(), GetColorProvider()); + ui::ColorId color = GetColorProvider() ? tabs::GetAlertIndicatorColor( + new_alert.value(), true, true) + : gfx::kPlaceholderColor; alert_state_indicator_->SetImage( tabs::GetAlertImageModel(new_alert.value(), color)); alert_state_indicator_->SetTooltipText(
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index 5188551f..623caeb0 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -868,13 +868,14 @@ } // For popup windows, draw location bar sides. + static constexpr int kLocationBarBorderThickness = 1; const SkColor location_bar_border_color = GetColorProvider()->GetColor(kColorLocationBarBorderOpaque); if (!tabstrip_visible && IsToolbarVisible()) { - gfx::Rect side(client_bounds.x() - kClientEdgeThickness, y, - kClientEdgeThickness, toolbar_bounds.height()); + gfx::Rect side(client_bounds.x() - kLocationBarBorderThickness, y, + kLocationBarBorderThickness, toolbar_bounds.height()); canvas->FillRect(side, location_bar_border_color); - side.Offset(client_bounds.width() + kClientEdgeThickness, 0); + side.Offset(client_bounds.width() + kLocationBarBorderThickness, 0); canvas->FillRect(side, location_bar_border_color); } }
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc index 1ab20a2..b934102 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.cc
@@ -193,7 +193,7 @@ // Maximized buttons start at window top, since the window has no border. This // offset is for the image (the actual clickable bounds extend all the way to // the top to take Fitts' Law into account). - return views::NonClientFrameView::kFrameShadowThickness; + return kFrameShadowThickness; } int OpaqueBrowserFrameViewLayout::CaptionButtonY(views::FrameButton button_id, @@ -229,8 +229,7 @@ // If we're the first button and maximized, add width to the right // hand side of the screen. return delegate_->IsFrameCondensed() && is_leading_button - ? kFrameBorderThickness - - views::NonClientFrameView::kFrameShadowThickness + ? kFrameBorderThickness - kFrameShadowThickness : 0; } if (forced_window_caption_spacing_ >= 0) {
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h index 9f7a0c0..a280652 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h
@@ -38,6 +38,7 @@ // Constants public for testing only. static constexpr int kNonClientExtraTopThickness = 1; + static constexpr int kFrameShadowThickness = 1; static const int kTopFrameEdgeThickness; static const int kSideFrameEdgeThickness; static const int kIconLeftSpacing;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc index 77825dc..75adc1b 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc
@@ -35,7 +35,7 @@ const int kCloseButtonWidth = 43; const int kMaximizedExtraCloseWidth = OpaqueBrowserFrameViewLayout::kFrameBorderThickness - - views::NonClientFrameView::kFrameShadowThickness; + OpaqueBrowserFrameViewLayout::kFrameShadowThickness; const int kCaptionButtonsWidth = kMinimizeButtonWidth + kMaximizeButtonWidth + kCloseButtonWidth; const int kCaptionButtonHeight = 18; @@ -190,7 +190,7 @@ int CaptionY() const { return delegate_->IsMaximized() ? 0 - : views::NonClientFrameView::kFrameShadowThickness; + : OpaqueBrowserFrameViewLayout::kFrameShadowThickness; } int CaptionLeft() const {
diff --git a/chrome/browser/ui/views/frame/windows_caption_button.cc b/chrome/browser/ui/views/frame/windows_caption_button.cc index 680c892..b654e14 100644 --- a/chrome/browser/ui/views/frame/windows_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_caption_button.cc
@@ -74,7 +74,7 @@ SkColor WindowsCaptionButton::GetBaseForegroundColor() const { return GetColorProvider()->GetColor( - frame_view_->ShouldPaintAsActive() + GetWidget()->ShouldPaintAsActive() ? kColorCaptionButtonForegroundActive : kColorCaptionButtonForegroundInactive); } @@ -186,7 +186,7 @@ const SkColor hovered_color = GetColorProvider()->GetColor(kColorCaptionCloseButtonForegroundHovered); if (!GetEnabled() || - (!frame_view_->ShouldPaintAsActive() && GetState() != STATE_HOVERED && + (!GetWidget()->ShouldPaintAsActive() && GetState() != STATE_HOVERED && GetState() != STATE_PRESSED)) { symbol_color = SkColorSetA(symbol_color, SkColorGetA(GetColorProvider()->GetColor(
diff --git a/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.cc b/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.cc new file mode 100644 index 0000000..be95d6f --- /dev/null +++ b/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.cc
@@ -0,0 +1,70 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/frame/windows_taskbar_icon_updater.h" + +#include "base/check_is_test.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/taskbar/taskbar_decorator_win.h" + +WindowsTaskbarIconUpdater::WindowsTaskbarIconUpdater(BrowserView& browser_view) + : browser_view_(browser_view) { + // The profile manager may by null in tests. + if (g_browser_process->profile_manager()) { + profile_observation_.Observe( + &g_browser_process->profile_manager()->GetProfileAttributesStorage()); + } else { + CHECK_IS_TEST(); + } + + browser_view_observer_.Observe(&*browser_view_); +} + +WindowsTaskbarIconUpdater::~WindowsTaskbarIconUpdater() = default; + +void WindowsTaskbarIconUpdater::OnProfileAdded( + const base::FilePath& profile_path) { + UpdateIcon(); +} + +void WindowsTaskbarIconUpdater::OnProfileWasRemoved( + const base::FilePath& profile_path, + const std::u16string& profile_name) { + UpdateIcon(); +} + +void WindowsTaskbarIconUpdater::OnProfileAvatarChanged( + const base::FilePath& profile_path) { + UpdateIcon(); +} + +void WindowsTaskbarIconUpdater::OnProfileHighResAvatarLoaded( + const base::FilePath& profile_path) { + UpdateIcon(); +} + +void WindowsTaskbarIconUpdater::OnViewAddedToWidget( + views::View* observed_view) { + // When the browser view is created, it does not yet have a widget; this + // attaches the widget when it is created. + browser_widget_observer_.Observe(observed_view->GetWidget()); + browser_view_observer_.Reset(); +} + +void WindowsTaskbarIconUpdater::OnWidgetVisibilityChanged(views::Widget* widget, + bool visible) { + // UpdateTaskbarDecoration() calls DrawTaskbarDecoration(), but that does + // nothing if the window is not visible. So even if we've already gotten the + // up-to-date decoration, we need to run the update procedure again here when + // the window becomes visible. + if (visible) { + UpdateIcon(); + } +} + +void WindowsTaskbarIconUpdater::UpdateIcon() { + taskbar::UpdateTaskbarDecoration(browser_view_->browser()->profile(), + browser_view_->GetNativeWindow()); +}
diff --git a/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.h b/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.h new file mode 100644 index 0000000..dc7fc27 --- /dev/null +++ b/chrome/browser/ui/views/frame/windows_taskbar_icon_updater.h
@@ -0,0 +1,51 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_WINDOWS_TASKBAR_ICON_UPDATER_H_ +#define CHROME_BROWSER_UI_VIEWS_FRAME_WINDOWS_TASKBAR_ICON_UPDATER_H_ + +#include "base/memory/raw_ref.h" +#include "base/scoped_observation.h" +#include "chrome/browser/profiles/profile_attributes_storage.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/views/view_observer.h" +#include "ui/views/widget/widget_observer.h" + +// Watches for profile changes and updates the window icon. +class WindowsTaskbarIconUpdater : public ProfileAttributesStorage::Observer, + public views::ViewObserver, + public views::WidgetObserver { + public: + explicit WindowsTaskbarIconUpdater(BrowserView& browser_view); + ~WindowsTaskbarIconUpdater() override; + + private: + // ProfileAttributesStorage::Observer: + void OnProfileAdded(const base::FilePath& profile_path) override; + void OnProfileWasRemoved(const base::FilePath& profile_path, + const std::u16string& profile_name) override; + void OnProfileAvatarChanged(const base::FilePath& profile_path) override; + void OnProfileHighResAvatarLoaded( + const base::FilePath& profile_path) override; + + // ViewObserver: + void OnViewAddedToWidget(views::View* observed_view) override; + + // WidgetObserver: + void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override; + + // Updates the taskbar icon for `browser_view_`'s window. + void UpdateIcon(); + + raw_ref<BrowserView> browser_view_; + base::ScopedObservation<views::View, views::ViewObserver> + browser_view_observer_{this}; + base::ScopedObservation<views::Widget, views::WidgetObserver> + browser_widget_observer_{this}; + base::ScopedObservation<ProfileAttributesStorage, + ProfileAttributesStorage::Observer> + profile_observation_{this}; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_FRAME_WINDOWS_TASKBAR_ICON_UPDATER_H_
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc index de9a017..3dc3cd9e 100644 --- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc +++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_host.cc
@@ -11,6 +11,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/app_mode/app_mode_utils.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -120,7 +121,7 @@ } ExclusiveAccessManager* const exclusive_access_manager = - browser_view_->browser()->exclusive_access_manager(); + browser_view_->browser()->GetFeatures().exclusive_access_manager(); // FullscreenControlHost UI is not needed for the keyboard input method in any // fullscreen mode except for tab-initiated fullscreen (and only when the user
diff --git a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc index 794c83d..e82eb66 100644 --- a/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/fullscreen_control/fullscreen_control_view_interactive_uitest.cc
@@ -12,6 +12,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" @@ -113,7 +114,7 @@ } ExclusiveAccessManager* GetExclusiveAccessManager() { - return browser()->exclusive_access_manager(); + return browser()->GetFeatures().exclusive_access_manager(); } ExclusiveAccessBubbleViews* GetExclusiveAccessBubble() {
diff --git a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc index 2887918..7ce6a835 100644 --- a/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc +++ b/chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.cc
@@ -7,6 +7,7 @@ #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -91,9 +92,11 @@ Browser* browser = chrome::FindBrowserWithTab(web_contents); // |browser| can be null in tests. if (browser) { - fullscreen_observation_.Observe( - browser->exclusive_access_manager()->fullscreen_controller()); - fullscreen_controller_ = browser->exclusive_access_manager() + fullscreen_observation_.Observe(browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller()); + fullscreen_controller_ = browser->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->GetWeakPtr(); }
diff --git a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc index 6367280..d3ceccd 100644 --- a/chrome/browser/ui/views/location_bar/selected_keyword_view.cc +++ b/chrome/browser/ui/views/location_bar/selected_keyword_view.cc
@@ -41,28 +41,27 @@ SelectedKeywordView::GetKeywordLabelNames(const std::u16string& keyword, const TemplateURLService* service) { KeywordLabelNames names; - if (service) { - const TemplateURL* template_url = - service->GetTemplateURLForKeyword(keyword); - bool is_extension_keyword = false; - bool is_gemini_keyword = false; - bool is_page_keyword = - template_url && - template_url->starter_pack_id() == TemplateURLStarterPackData::kPage; - names.short_name = service->GetKeywordShortName( - keyword, &is_extension_keyword, &is_gemini_keyword); - if (is_gemini_keyword) { - names.full_name = l10n_util::GetStringFUTF16( - IDS_OMNIBOX_SELECTED_KEYWORD_ASK_TEXT, names.short_name); - } else if (is_extension_keyword) { - names.full_name = names.short_name; - } else if (is_page_keyword) { - names.full_name = - l10n_util::GetStringUTF16(IDS_STARTER_PACK_PAGE_KEYWORD_TEXT); - } else { - names.full_name = l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT_MD, - names.short_name); - } + if (!service) + return names; + + const TemplateURL* template_url = service->GetTemplateURLForKeyword(keyword); + names.short_name = + template_url ? template_url->AdjustedShortNameForLocaleDirection() : u""; + + if (template_url && + template_url->starter_pack_id() == TemplateURLStarterPackData::kGemini) { + names.full_name = l10n_util::GetStringFUTF16( + IDS_OMNIBOX_SELECTED_KEYWORD_ASK_TEXT, names.short_name); + } else if (template_url && template_url->starter_pack_id() == + TemplateURLStarterPackData::kPage) { + names.full_name = + l10n_util::GetStringUTF16(IDS_STARTER_PACK_PAGE_KEYWORD_TEXT); + } else if (template_url && + template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION) { + names.full_name = names.short_name; + } else { + names.full_name = l10n_util::GetStringFUTF16(IDS_OMNIBOX_KEYWORD_TEXT_MD, + names.short_name); } return names; }
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc index 08ab5a98..f5738d73 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/tabs/public/tab_features.h" #include "chrome/browser/ui/ui_features.h" @@ -152,8 +153,9 @@ END_METADATA bool IsBrowserFullscreen(Browser* browser) { - DCHECK(browser->window() && - browser->exclusive_access_manager()->fullscreen_controller()); + DCHECK(browser->window() && browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller()); return browser->window()->IsFullscreen(); }
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_toast.cc b/chrome/browser/ui/views/passwords/password_change/password_change_toast.cc index 8aa0eeb..3974232 100644 --- a/chrome/browser/ui/views/passwords/password_change/password_change_toast.cc +++ b/chrome/browser/ui/views/passwords/password_change/password_change_toast.cc
@@ -133,7 +133,6 @@ layout_provider->GetDistanceMetric( DISTANCE_TOAST_BUBBLE_HEIGHT_ACTION_BUTTON))); action_button_->SetStyle(ui::ButtonStyle::kProminent); - action_button_->GetViewAccessibility().SetRole(ax::mojom::Role::kAlert); action_button_->SetProperty(views::kElementIdentifierKey, kPasswordChangeActionButton); action_button_->SetAppearDisabledInInactiveWidget(false); @@ -222,7 +221,15 @@ layout_provider->GetDistanceMetric( DISTANCE_TOAST_BUBBLE_HEIGHT_ACTION_BUTTON))); } - action_button_->SetVisible(configuration.action_button_text.has_value()); + if (configuration.action_button_text.has_value()) { + // Only set kAlert a11y role when text is not empty, otherwise it triggers + // a DCHECK in views::RunAccessibilityPaintChecks(). + action_button_->GetViewAccessibility().SetRole(ax::mojom::Role::kAlert); + action_button_->SetVisible(true); + } else { + action_button_->GetViewAccessibility().SetRole(ax::mojom::Role::kButton); + action_button_->SetVisible(false); + } close_button_->SetVisible(configuration.has_close_button); }
diff --git a/chrome/browser/ui/views/passwords/password_change/password_change_toast_browsertest.cc b/chrome/browser/ui/views/passwords/password_change/password_change_toast_browsertest.cc new file mode 100644 index 0000000..a329215 --- /dev/null +++ b/chrome/browser/ui/views/passwords/password_change/password_change_toast_browsertest.cc
@@ -0,0 +1,80 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/passwords/password_change/password_change_toast.h" + +#include <memory> + +#include "chrome/browser/password_manager/password_change_delegate_impl.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/passwords/password_change_ui_controller.h" +#include "chrome/browser/ui/test/test_browser_ui.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +const char kTestChangePasswordUrl[] = "https://example.com/change_password"; +const std::u16string kTestUsername = u"testuser"; +const std::u16string kTestPassword = u"password"; + +class PasswordChangeToastBrowserTest : public UiBrowserTest { + public: + PasswordChangeToastBrowserTest() = default; + ~PasswordChangeToastBrowserTest() override = default; + + PasswordChangeToastBrowserTest(const PasswordChangeToastBrowserTest&) = + delete; + PasswordChangeToastBrowserTest& operator=( + const PasswordChangeToastBrowserTest&) = delete; + + // UiBrowserTest: + void ShowUi(const std::string& name) override { + tabs::TabInterface* tab_interface = browser()->GetActiveTabInterface(); + ASSERT_TRUE(tab_interface); + + delegate_ = std::make_unique<PasswordChangeDelegateImpl>( + GURL(kTestChangePasswordUrl), kTestUsername, kTestPassword, + tab_interface); + + ui_controller_ = delegate_->ui_controller(); + + // Trigger the toast for the "Password Changed" state. + ui_controller_->UpdateState( + PasswordChangeDelegate::State::kPasswordSuccessfullyChanged); + } + + bool VerifyUi() override { + views::Widget* widget = ui_controller_->toast_view()->GetWidget(); + + auto* const test_info = + testing::UnitTest::GetInstance()->current_test_info(); + const std::string screenshot_name = + base::StrCat({test_info->test_suite_name(), "_", test_info->name()}); + + return VerifyPixelUi(widget, "PasswordChangeToastBrowserTest", + screenshot_name) != ui::test::ActionResult::kFailed; + } + + void DismissUi() override { + ui_controller_ = nullptr; + delegate_ = nullptr; + } + + void WaitForUserDismissal() override { + ui_test_utils::WaitForBrowserToClose(browser()); + } + + private: + std::unique_ptr<PasswordChangeDelegateImpl> delegate_; + raw_ptr<PasswordChangeUIController> ui_controller_; +}; + +IN_PROC_BROWSER_TEST_F(PasswordChangeToastBrowserTest, InvokeUi_Toast) { + ShowAndVerifyUi(); +} + +} // namespace
diff --git a/chrome/browser/ui/views/tabs/alert_indicator_button.cc b/chrome/browser/ui/views/tabs/alert_indicator_button.cc index 3854d3b..1e38c78 100644 --- a/chrome/browser/ui/views/tabs/alert_indicator_button.cc +++ b/chrome/browser/ui/views/tabs/alert_indicator_button.cc
@@ -364,8 +364,16 @@ } void AlertIndicatorButton::UpdateIconForAlertState(tabs::TabAlert state) { - const ui::ColorId color = parent_tab_->GetAlertIndicatorColor(state); + const ui::ColorId color = + parent_tab_->GetColorProvider() + ? tabs::GetAlertIndicatorColor( + state, + parent_tab_->tab_style_views()->GetApparentActiveState() == + TabActive::kActive, + GetWidget()->ShouldPaintAsActive()) + : gfx::kPlaceholderColor; const ui::ImageModel indicator_image = tabs::GetAlertImageModel(state, color); + SetImageModel(views::Button::STATE_NORMAL, indicator_image); SetImageModel(views::Button::STATE_DISABLED, indicator_image); SetImageModel(views::Button::STATE_PRESSED,
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc index c8e3fc6..10e29fd 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.cc
@@ -107,7 +107,6 @@ case CollaborationEvent::TAB_GROUP_REMOVED: case CollaborationEvent::COLLABORATION_ADDED: case CollaborationEvent::COLLABORATION_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: case CollaborationEvent::UNDEFINED: NOTREACHED(); }
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc index 75a46c00..75b1db6 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_browsertest.cc
@@ -91,7 +91,6 @@ case CollaborationEvent::COLLABORATION_MEMBER_ADDED: case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: return RecentActivityAction::kManageSharing; - case CollaborationEvent::VERSION_OUT_OF_DATE: case CollaborationEvent::UNDEFINED: return RecentActivityAction::kNone; }
diff --git a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_interactive_uitest.cc b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_interactive_uitest.cc index d42ee549..1a8af61 100644 --- a/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view_interactive_uitest.cc
@@ -83,7 +83,6 @@ case CollaborationEvent::COLLABORATION_MEMBER_ADDED: case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: return RecentActivityAction::kManageSharing; - case CollaborationEvent::VERSION_OUT_OF_DATE: case CollaborationEvent::UNDEFINED: return RecentActivityAction::kNone; }
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 6101492..348b07c6 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -28,7 +28,6 @@ #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" -#include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/browser/ui/tabs/alert/tab_alert.h" @@ -342,7 +341,7 @@ const int start = contents_rect.x(); #if BUILDFLAG(ENABLE_GLIC) - if (base::FeatureList::IsEnabled(features::kGlicTabGlow)) { + if (glic_border_view_) { glic_border_view_->SetBoundsRect(contents_rect); glic_border_view_->SetVisible(true); } @@ -860,55 +859,6 @@ controller_->GetGroupColorId(group().value())); } -ui::ColorId Tab::GetAlertIndicatorColor(tabs::TabAlert state) const { - const ui::ColorProvider* color_provider = GetColorProvider(); - if (!color_provider) { - return gfx::kPlaceholderColor; - } - - int group; - switch (state) { - case tabs::TabAlert::MEDIA_RECORDING: - case tabs::TabAlert::AUDIO_RECORDING: - case tabs::TabAlert::VIDEO_RECORDING: - case tabs::TabAlert::DESKTOP_CAPTURING: - group = 0; - break; - case tabs::TabAlert::TAB_CAPTURING: - case tabs::TabAlert::PIP_PLAYING: - case tabs::TabAlert::GLIC_ACCESSING: - case tabs::TabAlert::GLIC_SHARING: - group = 1; - break; - case tabs::TabAlert::AUDIO_PLAYING: - case tabs::TabAlert::AUDIO_MUTING: - case tabs::TabAlert::BLUETOOTH_CONNECTED: - case tabs::TabAlert::BLUETOOTH_SCAN_ACTIVE: - case tabs::TabAlert::USB_CONNECTED: - case tabs::TabAlert::HID_CONNECTED: - case tabs::TabAlert::SERIAL_CONNECTED: - case tabs::TabAlert::VR_PRESENTING_IN_HEADSET: - group = 2; - break; - } - - static constexpr std::array<std::array<std::array<ui::ColorId, 2>, 2>, 3> - color_ids{{{{{kColorTabAlertMediaRecordingInactiveFrameInactive, - kColorTabAlertMediaRecordingInactiveFrameActive}, - {kColorTabAlertMediaRecordingActiveFrameInactive, - kColorTabAlertMediaRecordingActiveFrameActive}}}, - {{{kColorTabAlertPipPlayingInactiveFrameInactive, - kColorTabAlertPipPlayingInactiveFrameActive}, - {kColorTabAlertPipPlayingActiveFrameInactive, - kColorTabAlertPipPlayingActiveFrameActive}}}, - {{{kColorTabAlertAudioPlayingInactiveFrameInactive, - kColorTabAlertAudioPlayingInactiveFrameActive}, - {kColorTabAlertAudioPlayingActiveFrameInactive, - kColorTabAlertAudioPlayingActiveFrameActive}}}}}; - return color_ids[group][tab_style_views()->GetApparentActiveState() == - TabActive::kActive] - [GetWidget()->ShouldPaintAsActive()]; -} bool Tab::IsActive() const { if (split()) {
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc index a9fc88f..8de86ff 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_20.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service_factory.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/ui_features.h" @@ -89,7 +90,7 @@ // Turn off IPH while the browser is showing fullscreen content (like a // video). See https://crbug.com/411475424. auto* const fullscreen_controller = - browser.exclusive_access_manager()->fullscreen_controller(); + browser.GetFeatures().exclusive_access_manager()->fullscreen_controller(); if (fullscreen_controller->IsWindowFullscreenForTabOrPending() || fullscreen_controller->IsExtensionFullscreenOrPending()) { return user_education::FeaturePromoResult::kBlockedByUi;
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc index 4c0c58af..c91f96ca1 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_controller_2x_interactive_uitest.cc
@@ -17,6 +17,7 @@ #include "base/time/time.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar_controller_util.h" @@ -645,7 +646,8 @@ WithElement(kTabId, [this](ui::TrackedElement* tab) { browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->EnterFullscreenModeForTab( AsInstrumentedWebContents(tab) @@ -655,7 +657,8 @@ CheckResult( [this]() { return browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsTabFullscreen(); }, @@ -676,7 +679,8 @@ WithElement(kTabId, [this](ui::TrackedElement* tab) { browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->EnterFullscreenModeForTab( AsInstrumentedWebContents(tab) @@ -686,7 +690,8 @@ WithElement(kTabId, [this](ui::TrackedElement* tab) { browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ExitFullscreenModeForTab( AsInstrumentedWebContents(tab)->web_contents()); @@ -694,7 +699,8 @@ CheckResult( [this]() { return browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsTabFullscreen(); },
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc index 8972947..31b61b7 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service.h" #include "chrome/browser/search_engine_choice/search_engine_choice_dialog_service_factory.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/location_bar/location_bar.h" @@ -88,8 +89,9 @@ user_education::FeaturePromoResult ContentNotFullscreenPrecondition::CheckPrecondition( ui::UnownedTypedDataCollection& data) const { - auto* const fullscreen_controller = - browser_->exclusive_access_manager()->fullscreen_controller(); + auto* const fullscreen_controller = browser_->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); if (fullscreen_controller->IsWindowFullscreenForTabOrPending() || fullscreen_controller->IsExtensionFullscreenOrPending()) { return user_education::FeaturePromoResult::kBlockedByUi;
diff --git a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc index 88798d4..3bbe9bb 100644 --- a/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/impl/browser_feature_promo_preconditions_interactive_uitest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/toolbar_controller_util.h" @@ -177,34 +178,35 @@ IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, Fullscreen) { DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTabId); - RunTestSequence( - InstrumentTab(kTabId), - NavigateWebContents(kTabId, - GURL(chrome::kChromeUIUserEducationInternalsURL)), - WithElement(kTabId, - [this](ui::TrackedElement* tab) { - browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->EnterFullscreenModeForTab( - AsInstrumentedWebContents(tab) - ->web_contents() - ->GetPrimaryMainFrame()); - }), - CheckResult( - [this]() { - return browser() - ->exclusive_access_manager() - ->fullscreen_controller() - ->IsTabFullscreen(); - }, - true), - CheckResult( - [this]() { - ContentNotFullscreenPrecondition precond(*browser()); - return precond.CheckPrecondition(data_); - }, - user_education::FeaturePromoResult::kBlockedByUi)); + RunTestSequence(InstrumentTab(kTabId), + NavigateWebContents( + kTabId, GURL(chrome::kChromeUIUserEducationInternalsURL)), + WithElement(kTabId, + [this](ui::TrackedElement* tab) { + browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller() + ->EnterFullscreenModeForTab( + AsInstrumentedWebContents(tab) + ->web_contents() + ->GetPrimaryMainFrame()); + }), + CheckResult( + [this]() { + return browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller() + ->IsTabFullscreen(); + }, + true), + CheckResult( + [this]() { + ContentNotFullscreenPrecondition precond(*browser()); + return precond.CheckPrecondition(data_); + }, + user_education::FeaturePromoResult::kBlockedByUi)); } IN_PROC_BROWSER_TEST_F(ContentNotFullscreenPreconditionUiTest, ExitFullscreen) { @@ -216,7 +218,8 @@ WithElement(kTabId, [this](ui::TrackedElement* tab) { browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->EnterFullscreenModeForTab( AsInstrumentedWebContents(tab) @@ -226,7 +229,8 @@ WithElement(kTabId, [this](ui::TrackedElement* tab) { browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->ExitFullscreenModeForTab( AsInstrumentedWebContents(tab)->web_contents()); @@ -234,7 +238,8 @@ CheckResult( [this]() { return browser() - ->exclusive_access_manager() + ->GetFeatures() + .exclusive_access_manager() ->fullscreen_controller() ->IsTabFullscreen(); },
diff --git a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc index e609e76..fa0d9e6 100644 --- a/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc +++ b/chrome/browser/ui/views/web_apps/protocol_handler_launch_dialog_view.cc
@@ -15,6 +15,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/mojom/dialog_button.mojom.h" +#include "ui/base/ui_base_types.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/controls/label.h" #include "ui/views/layout/layout_provider.h" @@ -79,10 +80,16 @@ auto view = std::make_unique<web_app::ProtocolHandlerLaunchDialogView>( url, profile, app_id, std::move(close_callback)); view->Init(); - views::DialogDelegate::CreateDialogWidget(std::move(view), - /*context=*/gfx::NativeWindow(), - /*parent=*/gfx::NativeView()) - ->Show(); + auto* widget = + views::DialogDelegate::CreateDialogWidget(std::move(view), + /*context=*/gfx::NativeWindow(), + /*parent=*/gfx::NativeView()); +#if BUILDFLAG(IS_CHROMEOS) + // On ChromeOS this dialog will be hidden underneath an existing Chrome + // instance unless kFloatingWindow is specified. + widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow); +#endif + widget->Show(); } } // namespace web_app
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index 316a589a..5d3b6ed 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -60,6 +60,7 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" @@ -1213,8 +1214,10 @@ if (!BeforeStateChangeAction(__FUNCTION__)) { return; } - FullscreenController* fullscreen_controller = - app_browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = app_browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); ASSERT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); ui_test_utils::ToggleFullscreenModeAndWait(app_browser()); ASSERT_TRUE(fullscreen_controller->IsFullscreenForBrowser()); @@ -1225,8 +1228,10 @@ if (!BeforeStateChangeAction(__FUNCTION__)) { return; } - FullscreenController* fullscreen_controller = - app_browser()->exclusive_access_manager()->fullscreen_controller(); + FullscreenController* fullscreen_controller = app_browser() + ->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller(); ASSERT_TRUE(fullscreen_controller->IsFullscreenForBrowser()); ui_test_utils::ToggleFullscreenModeAndWait(app_browser()); ASSERT_FALSE(fullscreen_controller->IsFullscreenForBrowser());
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc index 0a317e2..d924bf1 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog_browsertest.cc
@@ -17,7 +17,6 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/callback_helpers.h" -#include "base/json/json_parser.h" #include "base/json/json_reader.h" #include "base/path_service.h" #include "base/run_loop.h"
diff --git a/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.cc b/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.cc index 95c7ef1..a6d27c47 100644 --- a/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.cc +++ b/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/new_tab_footer/footer_context_menu.h" +#include "base/metrics/histogram_functions.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" @@ -14,6 +15,12 @@ DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(FooterContextMenu, kHideFooterIdForTesting); +namespace new_tab_footer { +void RecordContextMenuClick(FooterContextMenuItem item) { + base::UmaHistogramEnumeration("NewTabPage.Footer.ContextMenuClicked", item); +} +} // namespace new_tab_footer + FooterContextMenu::FooterContextMenu(Profile* profile) : ui::SimpleMenuModel(this), profile_(profile) { const int icon_size = 16; @@ -34,7 +41,8 @@ void FooterContextMenu::ExecuteCommand(int command_id, int event_flags) { switch (command_id) { case COMMAND_CLOSE_FOOTER: { - // TODO(crbug.com/420953182): Log when pressed. + new_tab_footer::RecordContextMenuClick( + new_tab_footer::FooterContextMenuItem::kHideFooter); profile_->GetPrefs()->SetBoolean(prefs::kNtpFooterVisible, false); break; }
diff --git a/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.h b/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.h index 870073f..e1ebbbaa 100644 --- a/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.h +++ b/chrome/browser/ui/webui/new_tab_footer/footer_context_menu.h
@@ -8,6 +8,15 @@ #include "base/memory/raw_ptr.h" #include "ui/menus/simple_menu_model.h" +namespace new_tab_footer { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class FooterContextMenuItem { + kHideFooter = 0, + kMaxValue = kHideFooter, +}; +} // namespace new_tab_footer + class Profile; // The context menu for the New Tab Page footer.
diff --git a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc index 0a405ad..305aab15 100644 --- a/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc +++ b/chrome/browser/ui/webui/new_tab_footer/new_tab_footer_handler_unittest.cc
@@ -8,6 +8,7 @@ #include "base/strings/string_util.h" #include "base/test/gmock_move_support.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/extension_service_test_base.h" @@ -311,12 +312,18 @@ } TEST_F(NewTabFooterHandlerExtensionTest, ContextMenu_HidesFooter) { + base::HistogramTester histogram_tester; + const std::string& hide_footer = "NewTabPage.Footer.ContextMenuClicked"; ASSERT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kNtpFooterVisible)); + histogram_tester.ExpectTotalCount(hide_footer, 0); FooterContextMenu menu(profile()); menu.ExecuteCommand(0 /* COMMAND_CLOSE_FOOTER */, /*event_flags=*/0); EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kNtpFooterVisible)); + histogram_tester.ExpectTotalCount(hide_footer, 1); + histogram_tester.ExpectBucketCount( + hide_footer, new_tab_footer::FooterContextMenuItem::kHideFooter, 1); } #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 5cbda19..41b310a 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1641,8 +1641,6 @@ {"enablePersonalizationLoggingDesc", IDS_SETTINGS_ENABLE_LOGGING_PREF_DESC}, {"spellingDescription", IDS_SETTINGS_SPELLING_PREF_DESC}, - {"linkDoctorPref", IDS_SETTINGS_LINKDOCTOR_PREF}, - {"linkDoctorPrefDesc", IDS_SETTINGS_LINKDOCTOR_PREF_DESC}, {"searchSuggestPref", IDS_SETTINGS_SUGGEST_PREF}, {"searchSuggestPrefDesc", IDS_SETTINGS_SUGGEST_PREF_DESC}, {"searchAggregatorSuggestPref", IDS_SETTINGS_SEARCH_AGGREGATOR_PREF},
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index c871371..c2c5d20 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -383,14 +383,14 @@ void CustomizeChromePageHandler::OpenChromeWebStore() { open_url_callback_.Run( - GURL("https://chrome.google.com/webstore?category=theme")); + GURL("https://chromewebstore.google.com/category/themes")); UMA_HISTOGRAM_ENUMERATION("NewTabPage.ChromeWebStoreOpen", NtpChromeWebStoreOpen::kAppearance); } void CustomizeChromePageHandler::OpenThirdPartyThemePage( const std::string& theme_id) { - open_url_callback_.Run(GURL("https://chrome.google.com/webstore/detail/" + + open_url_callback_.Run(GURL("https://chromewebstore.google.com/detail/" + base::EscapePath(theme_id))); UMA_HISTOGRAM_ENUMERATION("NewTabPage.ChromeWebStoreOpen", NtpChromeWebStoreOpen::kCollections);
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index b7c33133..3a72a50 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -704,7 +704,7 @@ GURL url; EXPECT_CALL(mock_open_url_callback_, Run).Times(1).WillOnce(SaveArg<0>(&url)); handler().OpenChromeWebStore(); - ASSERT_EQ(GURL("https://chrome.google.com/webstore?category=theme"), url); + ASSERT_EQ(GURL("https://chromewebstore.google.com/category/themes"), url); histogram_tester().ExpectTotalCount("NewTabPage.ChromeWebStoreOpen", 1); ASSERT_EQ( @@ -718,7 +718,7 @@ GURL url; EXPECT_CALL(mock_open_url_callback_, Run).Times(1).WillOnce(SaveArg<0>(&url)); handler().OpenThirdPartyThemePage("foo"); - ASSERT_EQ(GURL("https://chrome.google.com/webstore/detail/foo"), url); + ASSERT_EQ(GURL("https://chromewebstore.google.com/detail/foo"), url); histogram_tester().ExpectTotalCount("NewTabPage.ChromeWebStoreOpen", 1); ASSERT_EQ( histogram_tester().GetBucketCount("NewTabPage.ChromeWebStoreOpen",
diff --git a/chrome/browser/web_applications/app_service/publisher_helper.cc b/chrome/browser/web_applications/app_service/publisher_helper.cc index 24647f1..1a61d59 100644 --- a/chrome/browser/web_applications/app_service/publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/publisher_helper.cc
@@ -10,6 +10,8 @@ #include "components/webapps/browser/installable/installable_metrics.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chromeos/constants/chromeos_features.h" #endif @@ -36,4 +38,20 @@ return false; } +#if BUILDFLAG(IS_CHROMEOS) +std::vector<std::string> GetWebAppIdsForProtocolUrl(Profile* profile, + const GURL& protocol_url) { + if (!chromeos::features::IsWebAppManifestProtocolHandlerSupportEnabled() || + !apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) { + return {}; + } + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + std::vector<std::string> app_ids = proxy->GetAppIdsForUrl(protocol_url); + std::erase_if(app_ids, [&](const auto& app_id) { + return proxy->AppRegistryCache().GetAppType(app_id) != apps::AppType::kWeb; + }); + return app_ids; +} +#endif + } // namespace web_app
diff --git a/chrome/browser/web_applications/app_service/publisher_helper.h b/chrome/browser/web_applications/app_service/publisher_helper.h index 7f7f11a..6f9f53f 100644 --- a/chrome/browser/web_applications/app_service/publisher_helper.h +++ b/chrome/browser/web_applications/app_service/publisher_helper.h
@@ -5,10 +5,16 @@ #ifndef CHROME_BROWSER_WEB_APPLICATIONS_APP_SERVICE_PUBLISHER_HELPER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_APP_SERVICE_PUBLISHER_HELPER_H_ +#include <string> +#include <vector> + #include "chrome/browser/web_applications/web_app_constants.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "components/webapps/common/web_app_id.h" +#include "url/gurl.h" + +class Profile; namespace apps { enum class ShortcutSource; @@ -26,6 +32,13 @@ bool IsAppServiceShortcut(const webapps::AppId& web_app_id, const WebAppProvider& provider); +#if BUILDFLAG(IS_CHROMEOS) +// Consults the app service to figure out which web apps are capable of handling +// `protocol_url`. +std::vector<std::string> GetWebAppIdsForProtocolUrl(Profile* profile, + const GURL& protocol_url); +#endif + } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_APP_SERVICE_PUBLISHER_HELPER_H_
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index d54ce4f..082eb34 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -413,6 +413,22 @@ return filters; } +apps::IntentFilters CreateIntentFiltersFromProtocolHandlers( + const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers) { + apps::IntentFilters filters; + for (const auto& handler : protocol_handlers) { + auto intent_filter = std::make_unique<apps::IntentFilter>(); + intent_filter->AddSingleValueCondition(apps::ConditionType::kAction, + apps_util::kIntentActionView, + apps::PatternMatchType::kLiteral); + intent_filter->AddSingleValueCondition(apps::ConditionType::kScheme, + handler.protocol, + apps::PatternMatchType::kLiteral); + filters.push_back(std::move(intent_filter)); + } + return filters; +} + apps::IntentFilters CreateShareIntentFiltersFromShareTarget( const apps::ShareTarget& share_target) { apps::IntentFilters filters; @@ -646,6 +662,9 @@ CreateShareIntentFiltersFromShareTarget(*app.share_target())); } + base::Extend(filters, CreateIntentFiltersFromProtocolHandlers( + app.protocol_handlers())); + const apps::FileHandlers* enabled_file_handlers = provider.os_integration_manager().GetEnabledFileHandlers(app.app_id()); if (enabled_file_handlers) {
diff --git a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.cc b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.cc index 2b23122..b826b4aa 100644 --- a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.cc +++ b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.cc
@@ -5,35 +5,37 @@ #include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/content_settings/host_content_settings_map_factory.h" -#include "chrome/browser/password_manager/password_manager_settings_service_factory.h" -#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" -#include "chrome/browser/profiles/profile.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/password_manager/core/browser/password_manager_setting.h" +#include "components/password_manager/core/browser/password_manager_settings_service.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "url/origin.h" FederatedIdentityAutoReauthnPermissionContext:: FederatedIdentityAutoReauthnPermissionContext( - content::BrowserContext* browser_context) - : host_content_settings_map_( - HostContentSettingsMapFactory::GetForProfile(browser_context)), - permission_autoblocker_( - PermissionDecisionAutoBlockerFactory::GetForProfile( - Profile::FromBrowserContext(browser_context))), - browser_context_(browser_context) {} + HostContentSettingsMap* host_content_settings_map, + permissions::PermissionDecisionAutoBlocker* permission_autoblocker) + : host_content_settings_map_(host_content_settings_map), + permission_autoblocker_(permission_autoblocker) {} FederatedIdentityAutoReauthnPermissionContext:: ~FederatedIdentityAutoReauthnPermissionContext() = default; +void FederatedIdentityAutoReauthnPermissionContext:: + OnPasswordManagerSettingsServiceInitialized( + password_manager::PasswordManagerSettingsService* settings_service) { + password_manager_settings_service_ = settings_service; +} + +void FederatedIdentityAutoReauthnPermissionContext::Shutdown() { + password_manager_settings_service_ = nullptr; +} + bool FederatedIdentityAutoReauthnPermissionContext:: IsAutoReauthnSettingEnabled() { - password_manager::PasswordManagerSettingsService* settings_service = - PasswordManagerSettingsServiceFactory::GetForProfile( - Profile::FromBrowserContext(browser_context_)); - return settings_service && - settings_service->IsSettingEnabled( + return password_manager_settings_service_ && + password_manager_settings_service_->IsSettingEnabled( password_manager::PasswordManagerSetting::kAutoSignIn) && host_content_settings_map_->GetDefaultContentSetting( ContentSettingsType::FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION,
diff --git a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h index e5659241..34bad97 100644 --- a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h +++ b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h
@@ -6,13 +6,11 @@ #define CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION_CONTEXT_H_ #include "base/memory/raw_ptr.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/password_manager/core/browser/password_manager_settings_service.h" #include "content/public/browser/federated_identity_auto_reauthn_permission_context_delegate.h" -namespace content { -class BrowserContext; +namespace password_manager { +class PasswordManagerSettingsService; } namespace permissions { @@ -23,22 +21,38 @@ class Origin; } +class HostContentSettingsMap; + // Context for storing user permission to use the browser FedCM API's auto // sign-in feature. class FederatedIdentityAutoReauthnPermissionContext : public content::FederatedIdentityAutoReauthnPermissionContextDelegate, public KeyedService { public: - explicit FederatedIdentityAutoReauthnPermissionContext( - content::BrowserContext* browser_context); - - ~FederatedIdentityAutoReauthnPermissionContext() override; + // DO NOT pass a Profile here. Inject other keyed service dependencies + // explicitly and add a corresponding DependsOn() in the factory. See + // crbug.com/368297674. + // `host_content_settings_map` and `permission_autoblocker` must be non-null + // and outlive this service. + FederatedIdentityAutoReauthnPermissionContext( + HostContentSettingsMap* host_content_settings_map, + permissions::PermissionDecisionAutoBlocker* permission_autoblocker); FederatedIdentityAutoReauthnPermissionContext( const FederatedIdentityAutoReauthnPermissionContext&) = delete; FederatedIdentityAutoReauthnPermissionContext& operator=( const FederatedIdentityAutoReauthnPermissionContext&) = delete; + ~FederatedIdentityAutoReauthnPermissionContext() override; + + // Initializes cyclic dependency. `settings_service` must be non-null and + // can be used until Shutdown(). + void OnPasswordManagerSettingsServiceInitialized( + password_manager::PasswordManagerSettingsService* settings_service); + + // KeyedService: + void Shutdown() override; + // content::FederatedIdentityAutoReauthnPermissionContextDelegate: bool IsAutoReauthnSettingEnabled() override; bool IsAutoReauthnEmbargoed( @@ -57,7 +71,9 @@ const raw_ptr<HostContentSettingsMap> host_content_settings_map_; const raw_ptr<permissions::PermissionDecisionAutoBlocker, DanglingUntriaged> permission_autoblocker_; - const raw_ptr<content::BrowserContext> browser_context_; + + raw_ptr<password_manager::PasswordManagerSettingsService> + password_manager_settings_service_ = nullptr; }; #endif // CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION_CONTEXT_H_
diff --git a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.cc b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.cc index 3df8a56..3b7c0de 100644 --- a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.cc +++ b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.cc
@@ -6,6 +6,7 @@ #include "base/no_destructor.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h" @@ -40,6 +41,7 @@ .WithAshInternals(ProfileSelection::kOwnInstance) .Build()) { DependsOn(HostContentSettingsMapFactory::GetInstance()); + DependsOn(PermissionDecisionAutoBlockerFactory::GetInstance()); } FederatedIdentityAutoReauthnPermissionContextFactory:: @@ -48,7 +50,9 @@ std::unique_ptr<KeyedService> FederatedIdentityAutoReauthnPermissionContextFactory:: BuildServiceInstanceForBrowserContext( - content::BrowserContext* profile) const { + content::BrowserContext* browser_context) const { + Profile* profile = Profile::FromBrowserContext(browser_context); return std::make_unique<FederatedIdentityAutoReauthnPermissionContext>( - profile); + HostContentSettingsMapFactory::GetForProfile(profile), + PermissionDecisionAutoBlockerFactory::GetForProfile(profile)); }
diff --git a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h index 8c6770e..e171711 100644 --- a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h +++ b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h
@@ -28,7 +28,7 @@ // BrowserContextKeyedServiceFactory: std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( - content::BrowserContext* profile) const override; + content::BrowserContext* browser_context) const override; }; #endif // CHROME_BROWSER_WEBID_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION_CONTEXT_FACTORY_H_
diff --git a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_unittest.cc b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_unittest.cc index 4ea9545..d4c2efc 100644 --- a/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_unittest.cc +++ b/chrome/browser/webid/federated_identity_auto_reauthn_permission_context_unittest.cc
@@ -4,71 +4,129 @@ #include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context.h" +#include "base/containers/flat_map.h" #include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/test/task_environment.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/trusted_vault/trusted_vault_service_factory.h" #include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h" -#include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "content/public/test/browser_task_environment.h" +#include "components/password_manager/core/browser/password_manager_setting.h" +#include "components/password_manager/core/browser/password_manager_settings_service.h" +#include "components/permissions/permission_decision_auto_blocker.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" -class FederatedIdentityAutoReauthnPermissionContextTest : public testing::Test { - public: - FederatedIdentityAutoReauthnPermissionContextTest() = default; - ~FederatedIdentityAutoReauthnPermissionContextTest() override = default; - FederatedIdentityAutoReauthnPermissionContextTest( - FederatedIdentityAutoReauthnPermissionContextTest&) = delete; - FederatedIdentityAutoReauthnPermissionContextTest& operator=( - FederatedIdentityAutoReauthnPermissionContextTest&) = delete; +namespace { - void SetUp() override { - profile_ = - TestingProfile::Builder() - .AddTestingFactory(TrustedVaultServiceFactory::GetInstance(), - TrustedVaultServiceFactory::GetDefaultFactory()) - .AddTestingFactory(SyncServiceFactory::GetInstance(), - SyncServiceFactory::GetDefaultFactory()) - .Build(); - context_ = - FederatedIdentityAutoReauthnPermissionContextFactory::GetForProfile( - profile()); - host_content_settings_map_ = - HostContentSettingsMapFactory::GetForProfile(profile()); +class FakePasswordManagerSettingsService + : public password_manager::PasswordManagerSettingsService { + public: + FakePasswordManagerSettingsService() { + setting_enabled_map_ + [password_manager::PasswordManagerSetting::kOfferToSavePasswords] = + true; + setting_enabled_map_ + [password_manager::PasswordManagerSetting::kAutoSignIn] = true; + setting_enabled_map_[password_manager::PasswordManagerSetting:: + kBiometricReauthBeforePwdFilling] = true; } - Profile* profile() { return profile_.get(); } + FakePasswordManagerSettingsService( + const FakePasswordManagerSettingsService&) = delete; + FakePasswordManagerSettingsService& operator=( + const FakePasswordManagerSettingsService&) = delete; - protected: - raw_ptr<FederatedIdentityAutoReauthnPermissionContext, DanglingUntriaged> - context_; - raw_ptr<HostContentSettingsMap, DanglingUntriaged> host_content_settings_map_; + ~FakePasswordManagerSettingsService() override = default; + + // password_manager::PasswordManagerSettingsService implementation. + bool IsSettingEnabled( + password_manager::PasswordManagerSetting setting) const override { + return setting_enabled_map_.at(setting); + } + + void RequestSettingsFromBackend() override {} + + void TurnOffAutoSignIn() override { + setting_enabled_map_ + [password_manager::PasswordManagerSetting::kAutoSignIn] = false; + } + + private: + base::flat_map<password_manager::PasswordManagerSetting, bool> + setting_enabled_map_; +}; + +std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> +CreateAndRegisterPrefs() { + auto pref_service = + std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); + HostContentSettingsMap::RegisterProfilePrefs(pref_service->registry()); + return pref_service; +} + +class FederatedIdentityAutoReauthnPermissionContextTest : public testing::Test { + public: + FederatedIdentityAutoReauthnPermissionContextTest() { + context_.OnPasswordManagerSettingsServiceInitialized( + &password_manager_settings_service_); + } + + FederatedIdentityAutoReauthnPermissionContextTest( + const FederatedIdentityAutoReauthnPermissionContextTest&) = delete; + FederatedIdentityAutoReauthnPermissionContextTest& operator=( + const FederatedIdentityAutoReauthnPermissionContextTest&) = delete; + + ~FederatedIdentityAutoReauthnPermissionContextTest() override { + context_.Shutdown(); + host_content_settings_map_->ShutdownOnUIThread(); + } + + FederatedIdentityAutoReauthnPermissionContext& context() { return context_; } + + HostContentSettingsMap& host_content_settings_map() { + return *host_content_settings_map_; + } ContentSetting GetContentSetting(const GURL& rp_url) { - return host_content_settings_map_->GetContentSetting( + return host_content_settings_map().GetContentSetting( rp_url, rp_url, ContentSettingsType::FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION); } - content::BrowserTaskEnvironment* task_environment() { + base::test::SingleThreadTaskEnvironment* task_environment() { return &task_environment_; } private: - content::BrowserTaskEnvironment task_environment_{ + base::test::SingleThreadTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_ = + CreateAndRegisterPrefs(); + scoped_refptr<HostContentSettingsMap> host_content_settings_map_ = + base::MakeRefCounted<HostContentSettingsMap>( + pref_service_.get(), + /*is_off_the_record=*/false, + /*store_last_modified=*/false, + /*restore_session=*/false, + /*should_record_metrics=*/false); + permissions::PermissionDecisionAutoBlocker permission_decision_auto_blocker_{ + host_content_settings_map_.get()}; + FederatedIdentityAutoReauthnPermissionContext context_{ + host_content_settings_map_.get(), &permission_decision_auto_blocker_}; + FakePasswordManagerSettingsService password_manager_settings_service_; }; // Test that FedCM auto re-authn is opt-in by default. TEST_F(FederatedIdentityAutoReauthnPermissionContextTest, AutoReauthnEnabledByDefault) { GURL rp_url("https://rp.com"); - EXPECT_TRUE(context_->IsAutoReauthnSettingEnabled()); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_TRUE(context().IsAutoReauthnSettingEnabled()); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); } // Test that @@ -76,11 +134,11 @@ // blocks the permission if it is enabled. TEST_F(FederatedIdentityAutoReauthnPermissionContextTest, EnabledEmbargo) { GURL rp_url("https://rp.com"); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Embargoing `rp_url` should block the content setting for `rp_url`. - context_->RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + context().RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); } // Test that auto re-authn embargo only lasts for 10 mins (see @@ -88,45 +146,45 @@ // components/permissions/permission_decision_auto_blocker.cc) TEST_F(FederatedIdentityAutoReauthnPermissionContextTest, EmbargoAutoReset) { GURL rp_url("https://rp.com"); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Auto re-authn flow triggers embargo. - context_->RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + context().RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Auto re-authn is still in embargo state after 9 mins. task_environment()->FastForwardBy(base::Minutes(9)); - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Auto re-authn is no longer in embargo state after 11 mins. task_environment()->FastForwardBy(base::Minutes(2)); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); } // Test that embargo reset does not affect the `RequiresUserMediation` bit. TEST_F(FederatedIdentityAutoReauthnPermissionContextTest, EmbargoResetDoesNotAffectRequiresUserMediation) { GURL rp_url("https://rp.com"); - host_content_settings_map_->SetDefaultContentSetting( + host_content_settings_map().SetDefaultContentSetting( ContentSettingsType::FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION, CONTENT_SETTING_ALLOW); EXPECT_EQ(CONTENT_SETTING_ALLOW, GetContentSetting(rp_url)); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Auto re-authn flow triggers embargo. - context_->RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + context().RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // User signing out sets the `RequiresUserMediation` bit. - context_->SetRequiresUserMediation(url::Origin::Create(rp_url), true); + context().SetRequiresUserMediation(url::Origin::Create(rp_url), true); EXPECT_EQ(CONTENT_SETTING_BLOCK, GetContentSetting(rp_url)); // Auto re-authn is still in embargo state. - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // Auto re-authn is no longer in embargo state after 10 mins. task_environment()->FastForwardBy(base::Minutes(10)); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); // The`RequiresUserMediation` bit is not reset. EXPECT_EQ(CONTENT_SETTING_BLOCK, GetContentSetting(rp_url)); @@ -137,9 +195,11 @@ GURL rp_url("https://rp.com"); // Auto re-authn flow triggers embargo. - context_->RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); - EXPECT_TRUE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + context().RecordEmbargoForAutoReauthn(url::Origin::Create(rp_url)); + EXPECT_TRUE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); - context_->RemoveEmbargoForAutoReauthn(url::Origin::Create(rp_url)); - EXPECT_FALSE(context_->IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); + context().RemoveEmbargoForAutoReauthn(url::Origin::Create(rp_url)); + EXPECT_FALSE(context().IsAutoReauthnEmbargoed(url::Origin::Create(rp_url))); } + +} // namespace
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 0e5c4a70..e44c7dda 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1750422668-ba327da02ed85abc04c72d114916f51026bca817-281626e13af0a0d4ae66077035dc0f1f1b1e659c.profdata +chrome-android64-main-1750437161-9f0d2f2b3056cddddc34bdfaabf21ce190525094-f982c00e92433275a5cc54fbdbf93c6a67d7ca05.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index d58230ed..fb8857f 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1750427603-08c3fdd80ad0acb6925eb4c6ecdb00adf033609f-8dfa165541417eb3b81e872c27a43c138640adf5.profdata +chrome-mac-arm-main-1750442376-c2e7a966ba974e2fcaf07284a580e3bb5aeba341-75e06514b4370138759e63b67aae06c4bdf8090c.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 04bd71f..0d88d92 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -645,6 +645,14 @@ BASE_FEATURE(kGlicTabGlow, "GlicTabGlow", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kGlicParameterizedShader, + "GlicParameterizedShader", + base::FEATURE_DISABLED_BY_DEFAULT); +extern const base::FeatureParam<std::string> kGlicParameterizedShaderColors{ + &kGlicParameterizedShader, "glic-parameterized-shader-colors", ""}; +extern const base::FeatureParam<std::string> kGlicParameterizedShaderFloats{ + &kGlicParameterizedShader, "glic-parameterized-shader-floats", ""}; + BASE_FEATURE(kGlicMultiTab, "GlicMultiTab", base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(ENABLE_GLIC)
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index ddd0334..843b14a 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -364,6 +364,13 @@ BASE_DECLARE_FEATURE(kGlicTabGlow); COMPONENT_EXPORT(CHROME_FEATURES) +BASE_DECLARE_FEATURE(kGlicParameterizedShader); +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::FeatureParam<std::string> kGlicParameterizedShaderColors; +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::FeatureParam<std::string> kGlicParameterizedShaderFloats; + +COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicMultiTab); #endif // BUILDFLAG(ENABLE_GLIC)
diff --git a/chrome/credential_provider/DEPS b/chrome/credential_provider/DEPS index 7c83d700..b167f78 100644 --- a/chrome/credential_provider/DEPS +++ b/chrome/credential_provider/DEPS
@@ -8,6 +8,7 @@ "+extensions/common/switches.h", "+google_apis", "+net", + "+services/network/public/cpp", "+third_party/boringssl/src/include", "+third_party/re2", ]
diff --git a/chrome/credential_provider/test/BUILD.gn b/chrome/credential_provider/test/BUILD.gn index 41f4f7bf..8a662d38 100644 --- a/chrome/credential_provider/test/BUILD.gn +++ b/chrome/credential_provider/test/BUILD.gn
@@ -57,6 +57,7 @@ "//extensions/common", "//google_apis", "//net:test_support", + "//services/network/public/cpp:flags_and_switches", "//testing/gmock", "//testing/gtest", ]
diff --git a/chrome/credential_provider/test/gcp_gls_output_unittest.cc b/chrome/credential_provider/test/gcp_gls_output_unittest.cc index 0b7c46e..c87149ae 100644 --- a/chrome/credential_provider/test/gcp_gls_output_unittest.cc +++ b/chrome/credential_provider/test/gcp_gls_output_unittest.cc
@@ -13,6 +13,7 @@ #include "base/functional/bind.h" #include "base/json/json_writer.h" #include "base/process/launch.h" +#include "base/strings/stringprintf.h" #include "base/values.h" #include "base/win/windows_version.h" #include "chrome/browser/ui/startup/credential_provider_signin_dialog_win_test_data.h" @@ -23,7 +24,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" -#include "net/test/spawned_test_server/spawned_test_server.h" +#include "services/network/public/cpp/network_switches.h" #include "testing/gtest/include/gtest/gtest.h" namespace credential_provider { @@ -46,7 +47,7 @@ bool response_given_; }; - GcpUsingChromeTest(); + GcpUsingChromeTest() = default; void SetUp() override; void TearDown() override; @@ -85,7 +86,6 @@ CredentialProviderSigninDialogTestDataStorage test_data_storage_; net::test_server::EmbeddedTestServer gaia_server_; net::test_server::EmbeddedTestServer google_apis_server_; - net::SpawnedTestServer proxy_server_; TestGoogleApiResponse signin_token_response_; TestGoogleApiResponse user_info_response_; @@ -93,9 +93,6 @@ TestGoogleApiResponse mdm_token_response_; }; -GcpUsingChromeTest::GcpUsingChromeTest() - : proxy_server_(net::SpawnedTestServer::TYPE_PROXY, base::FilePath()) {} - void GcpUsingChromeTest::SetUp() { // Redirect connections to signin related pages to a handler that will // generate the needed headers and content to move the signin flow @@ -108,17 +105,11 @@ base::BindRepeating(&GcpUsingChromeTest::GoogleApisHtmlResponseHandler, base::Unretained(this))); EXPECT_TRUE(google_apis_server_.Start()); - - // Run a proxy server to redirect all non signin related requests to a - // page showing failed connections. - proxy_server_.set_redirect_connect_to_localhost(true); - EXPECT_TRUE(proxy_server_.Start()); } void GcpUsingChromeTest::TearDown() { EXPECT_TRUE(gaia_server_.ShutdownAndWaitUntilComplete()); EXPECT_TRUE(google_apis_server_.ShutdownAndWaitUntilComplete()); - EXPECT_TRUE(proxy_server_.Stop()); } std::string GcpUsingChromeTest::RunChromeAndExtractOutput() const { @@ -145,8 +136,16 @@ command_line.AppendSwitch(kGcpwSigninSwitch); command_line.AppendSwitchPath("user-data-dir", user_data_dir); - command_line.AppendSwitchASCII("proxy-server", - proxy_server_.host_port_pair().ToString()); + + // Redirect all requests to `gaia_server_` except those made to + // `google_apis_server_`. This results in any requests made by other Chrome + // modules being redirected harmlessly to `gaia_server_`. + command_line.AppendSwitchASCII( + network::switches::kHostResolverRules, + base::StringPrintf( + "MAP * %s, EXCLUDE %s", + gaia_server_.host_port_pair().ToString().c_str(), + google_apis_server_.host_port_pair().ToString().c_str())); return command_line; }
diff --git a/chrome/enterprise_companion/telemetry_logger/telemetry_logger.h b/chrome/enterprise_companion/telemetry_logger/telemetry_logger.h index 9d44704..76b7b7ea 100644 --- a/chrome/enterprise_companion/telemetry_logger/telemetry_logger.h +++ b/chrome/enterprise_companion/telemetry_logger/telemetry_logger.h
@@ -111,6 +111,7 @@ // If a delayed upload is scheduled, the timer class will hold a reference // to this class util the timer is triggered. void Flush(base::OnceClosure callback) { + VLOG(2) << __func__; owning_task_runner()->PostTask( FROM_HERE, base::BindOnce( @@ -234,10 +235,9 @@ delegate_->MinimumCooldownTime()); VLOG(1) << "Cooldown time received from server: " << response.next_request_wait_millis() << " ms"; - delegate_->StoreNextAllowedAttemptTime( - base::Time::Now() + cooldown_time, - base::BindOnce(&TelemetryLogger::SetCooldown, - base::WrapRefCounted(this), cooldown_time)); + SetCooldown(cooldown_time); + delegate_->StoreNextAllowedAttemptTime(base::Time::Now() + cooldown_time, + base::DoNothing()); } void SetCooldown(base::TimeDelta cooldown_time) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 5c7a723..ecc131b2 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3524,6 +3524,7 @@ "../browser/ui/views/location_bar/intent_chip_button_test_base.cc", "../browser/ui/views/location_bar/intent_chip_button_test_base.h", "../browser/ui/views/media_router/cast_dialog_coordinator_browsertest.cc", + "../browser/ui/views/passwords/password_change/password_change_toast_browsertest.cc", "../browser/ui/views/passwords/password_change/password_change_ui_browsertest.cc", "../browser/ui/views/privacy_sandbox/privacy_sandbox_dialog_view_browsertest.cc", "../browser/ui/views/profiles/avatar_toolbar_button_browsertest.cc",
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc index c17e430..79dc2045 100644 --- a/chrome/test/base/ui_test_utils.cc +++ b/chrome/test/base/ui_test_utils.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" @@ -520,7 +521,9 @@ FullscreenWaiter::FullscreenWaiter(Browser* browser, FullscreenWaiter::Expectation expectation) : expectation_(std::move(expectation)), - controller_(browser->exclusive_access_manager()->fullscreen_controller()), + controller_(browser->GetFeatures() + .exclusive_access_manager() + ->fullscreen_controller()), // Sometimes, the wait is called on a sequeunce, e.g. // as a part of interactive_ui_tests's RunTestSequence. // To handle that case, we can process pending task posted to the @@ -580,7 +583,10 @@ // The waiting condition is following the current implementation. // If the mode is either browser/tab fullscreen, it will be existed. // Otherwise, entering into browser fullscreen. - bool current = browser->exclusive_access_manager()->context()->IsFullscreen(); + bool current = browser->GetFeatures() + .exclusive_access_manager() + ->context() + ->IsFullscreen(); FullscreenWaiter waiter(browser, current ? FullscreenWaiter::kNoFullscreen : FullscreenWaiter::Expectation{ .browser_fullscreen = true});
diff --git a/chrome/test/data/webui/new_tab_footer/app_test.ts b/chrome/test/data/webui/new_tab_footer/app_test.ts index 5e9cf5b..3b801e6 100644 --- a/chrome/test/data/webui/new_tab_footer/app_test.ts +++ b/chrome/test/data/webui/new_tab_footer/app_test.ts
@@ -415,6 +415,9 @@ container.dispatchEvent(new MouseEvent('contextmenu')); await handler.whenCalled('showContextMenu'); + assertEquals( + 1, + metrics.count('NewTabPage.Footer.Click', FooterElement.CONTEXT_MENU)); }); });
diff --git a/chrome/test/data/webui/settings/checkbox_test.ts b/chrome/test/data/webui/settings/checkbox_test.ts index dd26328..2f961eb 100644 --- a/chrome/test/data/webui/settings/checkbox_test.ts +++ b/chrome/test/data/webui/settings/checkbox_test.ts
@@ -4,8 +4,10 @@ import 'chrome://settings/lazy_load.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import type {SettingsCheckboxElement} from 'chrome://settings/lazy_load.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {eventToPromise} from 'chrome://webui-test/test_util.js'; /** @fileoverview Suite of tests for settings-checkbox. */ suite('SettingsCheckbox', function() { @@ -85,4 +87,77 @@ assertTrue(testElement.checked); assertEquals(1, prefNum.value); }); + + test('sub label should be able to have an id', () => { + testElement.subLabelHtml = `<a id="subLabelWithLink"></a>`; + flush(); + + const actionLink = + testElement.$.subLabel.querySelector('#subLabelWithLink'); + assertTrue(!!actionLink); + }); + + test('sub label should be able to have an aria-label', () => { + testElement.subLabelHtml = `<a aria-label="Label"></a>`; + flush(); + + const actionLink = testElement.$.subLabel.querySelector('a'); + assertTrue(!!actionLink); + assertEquals(actionLink.getAttribute('aria-label'), 'Label'); + }); + + test( + 'click on sub label link should not toggle the button', async function() { + testElement.checked = true; + testElement.subLabelHtml = `<a href="#"></a>`; + flush(); + + const actionLink = testElement.$.subLabel.querySelector('a'); + assertTrue(!!actionLink); + + assertTrue(testElement.checked); + + actionLink.click(); + await testElement.$.checkbox.updateComplete; + + assertTrue(testElement.checked); + }); + + test('click on sub label text should toggle the button', async function() { + testElement.checked = true; + testElement.subLabelHtml = `<a href="#"></a>`; + flush(); + + assertTrue(testElement.checked); + + testElement.$.subLabel.click(); + await testElement.$.checkbox.updateComplete; + + assertFalse(testElement.checked); + }); + + test('click on sub label link should fire a custom event', async function() { + testElement.subLabelHtml = `<a href="#" id="subLabelWithLink"></a>`; + flush(); + + const actionLink = testElement.$.subLabel.querySelector('a'); + assertTrue(!!actionLink); + + const clickEventPromise = + eventToPromise('sub-label-link-clicked', testElement); + actionLink.click(); + const clickEvent = await clickEventPromise; + assertEquals('subLabelWithLink', clickEvent.detail.id); + }); + + test('click on sub label text should not fire a custom event', () => { + testElement.subLabelHtml = `<a href="#" id="subLabelWithLink"></a>`; + testElement.addEventListener('sub-label-link-clicked', () => { + assertNotReached( + 'custom event should not be triggered for non action link clicks.'); + }); + flush(); + + testElement.$.subLabel.click(); + }); });
diff --git a/chrome/test/data/webui/settings/clear_browsing_data_dialog_v2_test.ts b/chrome/test/data/webui/settings/clear_browsing_data_dialog_v2_test.ts index 468a74a..9b6d54e30 100644 --- a/chrome/test/data/webui/settings/clear_browsing_data_dialog_v2_test.ts +++ b/chrome/test/data/webui/settings/clear_browsing_data_dialog_v2_test.ts
@@ -10,17 +10,19 @@ import type {ClearBrowsingDataResult, SettingsCheckboxElement, SettingsClearBrowsingDataDialogV2Element, SettingsHistoryDeletionDialogElement} from 'chrome://settings/lazy_load.js'; import {BrowsingDataType, ClearBrowsingDataBrowserProxyImpl, getDataTypePrefName, getTimePeriodString, TimePeriod} from 'chrome://settings/lazy_load.js'; import type {SettingsPrefsElement} from 'chrome://settings/settings.js'; -import {CrSettingsPrefs, SignedInState} from 'chrome://settings/settings.js'; +import {CrSettingsPrefs, SignedInState, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {assertArrayEquals, assertEquals, assertFalse, assertNotReached, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js'; import {TestClearBrowsingDataBrowserProxy} from './test_clear_browsing_data_browser_proxy.js'; +import {TestSyncBrowserProxy} from './test_sync_browser_proxy.js'; // clang-format on suite('DeleteBrowsingDataDialog', function() { let testClearBrowsingDataBrowserProxy: TestClearBrowsingDataBrowserProxy; + let testSyncBrowserProxy: TestSyncBrowserProxy; let dialog: SettingsClearBrowsingDataDialogV2Element; let settingsPrefs: SettingsPrefsElement; @@ -33,6 +35,9 @@ testClearBrowsingDataBrowserProxy = new TestClearBrowsingDataBrowserProxy(); ClearBrowsingDataBrowserProxyImpl.setInstance( testClearBrowsingDataBrowserProxy); + testSyncBrowserProxy = new TestSyncBrowserProxy(); + SyncBrowserProxyImpl.setInstance(testSyncBrowserProxy); + setClearBrowsingDataPrefs(false); return createDialog(); }); @@ -500,7 +505,7 @@ const historyCheckbox = getCheckboxForDataType(BrowsingDataType.HISTORY); assertTrue(!!historyCheckbox); - assertEquals('history result', historyCheckbox.subLabel); + assertEquals('history result', historyCheckbox.subLabelHtml); // Case 2, Counter updates a checkbox in the more options list. // Simulate a browsing data counter result for Site settings. The Site @@ -515,7 +520,7 @@ const siteSettingsCheckbox = getCheckboxForDataType(BrowsingDataType.SITE_SETTINGS); assertTrue(!!siteSettingsCheckbox); - assertEquals('site settings result', siteSettingsCheckbox.subLabel); + assertEquals('site settings result', siteSettingsCheckbox.subLabelHtml); }); test('ClearBrowsingData', async function() { @@ -777,4 +782,23 @@ deletionEvent2.detail.deletionConfirmationText, loadTimeData.getString('deletionConfirmationAllTimeToast')); }); + + // <if expr="not is_chromeos"> + test('SignOutLink', async function() { + // Pass a dummy string with an anchor element and id=signOutLink since the + // actual signOut string is passed from the C++ side. + webUIListenerCallback( + 'browsing-data-counter-text-update', 'browser.clear_data.cookies', + `<a href="#" id="signOutLink"></a>`); + await flushTasks(); + + const cookiesCheckbox = getCheckboxForDataType(BrowsingDataType.SITE_DATA); + assertTrue(!!cookiesCheckbox); + + const signOutLink = cookiesCheckbox.$.subLabel.querySelector('a'); + assertTrue(!!signOutLink); + signOutLink.click(); + await testSyncBrowserProxy.whenCalled('signOut'); + }); + // </if> });
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index cf7f66f..ae6e255 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -392,6 +392,11 @@ "NotebookLmAppShelfPinReset", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables support for protocols handlers registered via web app manifest. +BASE_FEATURE(kWebAppManifestProtocolHandlerSupport, + "WebAppManifestProtocolHandlerSupport", + base::FEATURE_ENABLED_BY_DEFAULT); + const char kRoundedWindowsRadius[] = "window_radius"; bool IsApnPoliciesEnabled() { @@ -602,4 +607,8 @@ /*default_value=*/12); } +bool IsWebAppManifestProtocolHandlerSupportEnabled() { + return base::FeatureList::IsEnabled(kWebAppManifestProtocolHandlerSupport); +} + } // namespace chromeos::features
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 2f191f5af..77c58d1 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -127,6 +127,8 @@ BASE_DECLARE_FEATURE(kNotebookLmAppShelfPin); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kNotebookLmAppShelfPinReset); +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +BASE_DECLARE_FEATURE(kWebAppManifestProtocolHandlerSupport); // Keep alphabetized. @@ -205,6 +207,8 @@ bool IsMicrosoftOneDriveIntegrationForEnterpriseEnabled(); COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsFeatureManagementHistoryEmbeddingEnabled(); +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +bool IsWebAppManifestProtocolHandlerSupportEnabled(); } // namespace features } // namespace chromeos
diff --git a/chromeos/ui/frame/non_client_frame_view_interactive_uitest.cc b/chromeos/ui/frame/non_client_frame_view_interactive_uitest.cc index 6e45818..def5a1d 100644 --- a/chromeos/ui/frame/non_client_frame_view_interactive_uitest.cc +++ b/chromeos/ui/frame/non_client_frame_view_interactive_uitest.cc
@@ -58,13 +58,13 @@ chromeos::FrameCaptionButtonContainerView::TestApi test_api( header_view()->caption_button_container()); - EXPECT_TRUE(frame_view()->ShouldPaintAsActive()); + EXPECT_TRUE(frame_view()->GetWidget()->ShouldPaintAsActive()); EXPECT_TRUE(test_api.size_button()->GetPaintAsActive()); widget()->Deactivate(); ASSERT_TRUE(base::test::RunUntil([&]() { return !widget()->IsActive(); })); - EXPECT_FALSE(frame_view()->ShouldPaintAsActive()); + EXPECT_FALSE(frame_view()->GetWidget()->ShouldPaintAsActive()); EXPECT_FALSE(test_api.size_button()->GetPaintAsActive()); }
diff --git a/clank b/clank index 02d6754..87688db 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 02d6754dd5cd180b7288bcbaed9b9e0a8a66b395 +Subproject commit 87688db09fa1af75f935e82e11b7e21594f2c443
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_instance.cc b/components/autofill/core/browser/data_model/autofill_ai/entity_instance.cc index f9d989d..b2e3146 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_instance.cc +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_instance.cc
@@ -52,10 +52,12 @@ const std::string& app_locale, base::optional_ref<const std::u16string> format_string) const { field_type = GetNormalizedFieldType(field_type); - if (field_type == UNKNOWN_TYPE) { - return u""; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (field_type == UNKNOWN_TYPE) { + return u""; + } + CHECK(type_.field_subtypes().contains(field_type)); } - CHECK(type_.field_subtypes().contains(field_type)); return std::visit( absl::Overload{[&](const CountryInfo& country) { return country.GetCountryName(app_locale); @@ -82,10 +84,12 @@ std::u16string AttributeInstance::GetRawInfo(GetRawInfoPassKey, FieldType field_type) const { field_type = GetNormalizedFieldType(field_type); - if (field_type == UNKNOWN_TYPE) { - return u""; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (field_type == UNKNOWN_TYPE) { + return u""; + } + CHECK(type_.field_subtypes().contains(field_type)); } - CHECK(type_.field_subtypes().contains(field_type)); return std::visit( absl::Overload{ [&](const CountryInfo& country) { @@ -106,10 +110,12 @@ VerificationStatus AttributeInstance::GetVerificationStatus( FieldType field_type) const { field_type = GetNormalizedFieldType(field_type); - if (field_type == UNKNOWN_TYPE) { - return VerificationStatus::kNoStatus; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (field_type == UNKNOWN_TYPE) { + return VerificationStatus::kNoStatus; + } + CHECK(type_.field_subtypes().contains(field_type)); } - CHECK(type_.field_subtypes().contains(field_type)); return std::visit( absl::Overload{ [&](const CountryInfo&) { return VerificationStatus::kNoStatus; }, @@ -131,10 +137,12 @@ std::u16string_view format_string, VerificationStatus status) { field_type = GetNormalizedFieldType(field_type); - if (field_type == UNKNOWN_TYPE) { - return; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (field_type == UNKNOWN_TYPE) { + return; + } + CHECK(type_.field_subtypes().contains(field_type)); } - CHECK(type_.field_subtypes().contains(field_type)); std::visit( absl::Overload{ [&](CountryInfo& country) { @@ -165,10 +173,12 @@ const std::u16string& value, VerificationStatus status) { field_type = GetNormalizedFieldType(field_type); - if (field_type == UNKNOWN_TYPE) { - return; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (field_type == UNKNOWN_TYPE) { + return; + } + CHECK(type_.field_subtypes().contains(field_type)); } - CHECK(type_.field_subtypes().contains(field_type)); std::visit(absl::Overload{ [&](CountryInfo& country) { if (!country.SetCountryFromCountryCode(value)) { @@ -192,31 +202,37 @@ FieldType AttributeInstance::GetNormalizedFieldType( FieldType field_type) const { - if (type_.field_subtypes().contains(field_type)) { - return field_type; + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { + if (type_.field_subtypes().contains(field_type)) { + return field_type; + } + if (field_type == type_.field_type()) { + // In some cases, a field might have `AutofillField::Type()` being the one + // corresponding to a structured attribute (e.g., PASSPORT_NAME_TAG). This + // should not usually happen but for now can, only in case a field + // couldn't be classified by Autofill's logic but was classified by the ML + // model. In that case, we assume the type is the top-level type of the + // attribute. + return std::visit( + absl::Overload{ + [&](const CountryInfo&) { return type_.field_type(); }, + [&](const DateInfo&) { return type_.field_type(); }, + [&](const NameInfo&) { return NAME_FULL; }, + [&](const StateInfo&) { return type_.field_type(); }, + [&](const std::u16string&) { return type_.field_type(); }}, + info_); + } + // In case the field classification is totally unrelated to the + // attribute type classification, we return UKNOWN_TYPE if the attribute is + // structured because we don't have information on how to break down the + // attribute with the given type. If the type is not structured we just + // return the corresponding field type of the attribute, just like we would + // do regardless of the type passed. + return IsTagType(type_.field_type()) ? UNKNOWN_TYPE : type_.field_type(); } - if (field_type == type_.field_type()) { - // In some cases, a field might have `AutofillField::Type()` being the one - // corresponding to a structured attribute (e.g., PASSPORT_NAME_TAG). This - // should not usually happen but for now can, only in case a field couldn't - // be classified by Autofill's logic but was classified by the ML model. In - // that case, we assume the type is the top-level type of the attribute. - return std::visit( - absl::Overload{ - [&](const CountryInfo&) { return type_.field_type(); }, - [&](const DateInfo&) { return type_.field_type(); }, - [&](const NameInfo&) { return NAME_FULL; }, - [&](const StateInfo&) { return type_.field_type(); }, - [&](const std::u16string&) { return type_.field_type(); }}, - info_); - } - // In case the field classification is totally unrelated to the - // attribute type classification, we return UKNOWN_TYPE if the attribute is - // structured because we don't have information on how to break down the - // attribute with the given type. If the type is not structured we just return - // the corresponding field type of the attribute, just like we would do - // regardless of the type passed. - return IsTagType(type_.field_type()) ? UNKNOWN_TYPE : type_.field_type(); + + return type_.field_subtypes().contains(field_type) ? field_type + : type_.field_type(); } void AttributeInstance::FinalizeInfo() {
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc b/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc index c4f3f6f..5dbeb82 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc
@@ -14,29 +14,6 @@ namespace autofill { -// AttributeType::field_type() must be injective: distinct AttributeTypes must -// be mapped to distinct FieldTypes. -static_assert( - std::ranges::all_of(DenseSet<AttributeType>::all(), [](AttributeType a) { - return std::ranges::all_of( - DenseSet<AttributeType>::all(), [&a](AttributeType b) { - return a == b || a.field_type() != b.field_type(); - }); - })); - -// static -std::optional<AttributeType> AttributeType::FromFieldType(FieldType type) { - // This lookup table is the inverse of AttributeType::field_type(). - static constexpr auto kTable = []() { - std::array<std::optional<AttributeType>, MAX_VALID_FIELD_TYPE> arr{}; - for (AttributeType at : DenseSet<AttributeType>::all()) { - arr[at.field_type()] = at; - } - return arr; - }(); - return 0 <= type && type < kTable.size() ? kTable[type] : std::nullopt; -} - FieldTypeSet AttributeType::storable_field_types( base::PassKey<EntityTable> pass_key) const { if (data_type() == DataType::kName) {
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h index f402a06..1b5f8643 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h
@@ -61,9 +61,6 @@ static bool DisambiguationOrder(const AttributeType& lhs, const AttributeType& rhs); - // Maps each Autofill AI `FieldType` to the corresponding AttributeType. - static std::optional<AttributeType> FromFieldType(FieldType type); - constexpr explicit AttributeType(AttributeTypeName n) : name_(n) {} constexpr AttributeType(const AttributeType&) = default; @@ -79,7 +76,11 @@ // There are three kinds of AttributeType / FieldType associations: // - `field_type()` is the one that best describes the full attribute. - // Except for name types, `FromFieldType(field_type()) == field_type()`. + // If kAutofillAiNoTagTypes is disabled: + // The `field_type()` uniquely identifies the AttributeType. + // If kAutofillAiNoTagTypes is enabled: + // Except for name types, the `field_type()` uniquely identifies the + // AttributeType. // - `field_subtypes()` additionally include more fine-granular ones. // Except for name types, `field_subtypes() == {field_type}`. // For name types, `field_subtypes()` includes `NAME_FIRST` etc.
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type_unittest.cc b/components/autofill/core/browser/data_model/autofill_ai/entity_type_unittest.cc index b69ce04..b9178f0c 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type_unittest.cc +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type_unittest.cc
@@ -25,7 +25,6 @@ NAME_LAST_SECOND, NAME_LAST_CONJUNCTION, NAME_MIDDLE_INITIAL, NAME_FULL, NAME_SUFFIX, ALTERNATIVE_FAMILY_NAME, ALTERNATIVE_GIVEN_NAME, ALTERNATIVE_FULL_NAME)); - EXPECT_EQ(a, AttributeType::FromFieldType(PASSPORT_NAME_TAG)); } TEST(AutofillAttributeTypeTest, IsObfuscated) {
diff --git a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc index 1de839e..7262fed1 100644 --- a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc +++ b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc
@@ -28,10 +28,32 @@ base::flat_map<EntityType, std::vector<AutofillFieldWithAttributeType>>; using SectionMap = base::flat_map<Section, EntityMap>; +// AttributeType::field_type() must be injective: distinct AttributeTypes must +// be mapped to distinct FieldTypes. +static_assert( + std::ranges::all_of(DenseSet<AttributeType>::all(), [](AttributeType a) { + return std::ranges::all_of( + DenseSet<AttributeType>::all(), [&a](AttributeType b) { + return a == b || a.field_type() != b.field_type(); + }); + })); + std::optional<AttributeType> GetStaticAttributeType( const AutofillField& field) { + // This lookup table is the inverse of AttributeType::field_type(). + static constexpr auto kTable = []() { + std::array<std::optional<AttributeType>, MAX_VALID_FIELD_TYPE> arr{}; + for (AttributeType at : DenseSet<AttributeType>::all()) { + arr[at.field_type()] = at; + } + return arr; + }(); + std::optional<FieldType> ft = field.GetAutofillAiServerTypePredictions(); - return ft ? AttributeType::FromFieldType(*ft) : std::nullopt; + if (!ft) { + return std::nullopt; + } + return 0 <= *ft && *ft < kTable.size() ? kTable[*ft] : std::nullopt; } // The `i`th element of the returned vector contains the type of `fields[i]`.
diff --git a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager_unittest.cc b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager_unittest.cc index fe48d2b..935e85e1 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager_unittest.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager_unittest.cc
@@ -319,15 +319,10 @@ return form; } - std::u16string GetValueFromEntityForFieldType(const EntityInstance entity, - FieldType type, - const std::string& app_locale) { - std::optional<AttributeType> attribute = AttributeType::FromFieldType(type); - CHECK(attribute); - base::optional_ref<const AttributeInstance> instance = - entity.attribute(*attribute); - CHECK(instance); - return instance->GetInfo(type, app_locale, /*format_string=*/std::nullopt); + std::u16string GetValueFromEntity(const EntityInstance entity, + AttributeType attribute, + const std::string& app_locale = "") { + return entity.attribute(attribute)->GetCompleteInfo(app_locale); } std::u16string GetValueFromEntityForAttributeTypeName( @@ -720,14 +715,15 @@ // In this test, we simulate the user submitting a form with data that is // already contained in one of the entities. TEST_F(AutofillAiManagerImportFormTest, EntityAlreadyStored_DoNotShowPrompt) { + using enum AttributeTypeName; std::unique_ptr<FormStructure> form = CreateFormStructure({DRIVERS_LICENSE_NAME_TAG, DRIVERS_LICENSE_NUMBER}); EntityInstance entity = test::GetDriversLicenseEntityInstance(); // Set the filled values to be the same as the ones already stored. - form->field(0)->set_value(GetValueFromEntityForFieldType( - entity, DRIVERS_LICENSE_NAME_TAG, /*app_locale=*/"")); - form->field(1)->set_value(GetValueFromEntityForFieldType( - entity, DRIVERS_LICENSE_NUMBER, /*app_locale=*/"")); + form->field(0)->set_value( + GetValueFromEntity(entity, AttributeType(kDriversLicenseName))); + form->field(1)->set_value( + GetValueFromEntity(entity, AttributeType(kDriversLicenseNumber))); AddOrUpdateEntityInstance(entity); EXPECT_CALL(autofill_client(), ShowEntitySaveOrUpdateBubble).Times(0); @@ -781,6 +777,7 @@ } TEST_F(AutofillAiManagerImportFormTest, UpdateEntity_ShowPromptAndAccept) { + using enum AttributeTypeName; // The submitted form will have issue date info. std::unique_ptr<FormStructure> form = CreateFormStructure({PASSPORT_NAME_TAG, PASSPORT_NUMBER, @@ -795,12 +792,12 @@ // Set the filled values to be the same as the ones already stored in the // existing entity, also fill the issue and expiry dates. - form->field(0)->set_value(GetValueFromEntityForFieldType( - existing_entity_without_issue_and_expiry_dates, PASSPORT_NAME_TAG, - /*app_locale=*/"")); - form->field(1)->set_value(GetValueFromEntityForFieldType( - existing_entity_without_issue_and_expiry_dates, PASSPORT_NUMBER, - /*app_locale=*/"")); + form->field(0)->set_value( + GetValueFromEntity(existing_entity_without_issue_and_expiry_dates, + AttributeType(kPassportName))); + form->field(1)->set_value( + GetValueFromEntity(existing_entity_without_issue_and_expiry_dates, + AttributeType(kPassportNumber))); // Issue date. form->field(2)->set_value(u"01/02/16"); form->field(2)->set_format_string_unless_overruled(
diff --git a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc index 715c90ba..c93bb92d 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc
@@ -62,12 +62,11 @@ }); } -std::u16string GetEntityInstanceValueForFieldType( +std::u16string GetEntityInstanceValue( const EntityInstance entity, - FieldType type, + AttributeType attribute, const std::string& app_locale = kAppLocaleUS) { - return entity.attribute(*AttributeType::FromFieldType(type)) - ->GetInfo(type, app_locale, /*format_string=*/std::nullopt); + return entity.attribute(attribute)->GetCompleteInfo(app_locale); } std::optional<std::u16string> GetFillValueForField( @@ -126,6 +125,8 @@ std::vector<EntityInstance> entities = {passport_entity}; FieldType triggering_field_type = PASSPORT_NAME_TAG; + AttributeType triggering_attribute_type = + AttributeType(AttributeTypeName::kPassportName); std::unique_ptr<FormStructure> form = CreateFormStructure( {triggering_field_type, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); std::vector<Suggestion> suggestions = CreateFillingSuggestions( @@ -135,8 +136,7 @@ // value for the `triggering_field_type`. EXPECT_EQ(suggestions.size(), 3u); EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValueForFieldType(passport_entity, - triggering_field_type)); + GetEntityInstanceValue(passport_entity, triggering_attribute_type)); EXPECT_EQ(suggestions[1].type, SuggestionType::kSeparator); EXPECT_EQ(suggestions[2].type, SuggestionType::kManageAutofillAi); @@ -147,12 +147,12 @@ // The triggering/first field is of AutofillAi Type. EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[0]), - GetEntityInstanceValueForFieldType(passport_entity, - triggering_field_type)); + GetEntityInstanceValue(passport_entity, triggering_attribute_type)); // The second field in the form is also of AutofillAi. EXPECT_EQ( GetFillValueForField(entities, *payload, *form->fields()[1]), - GetEntityInstanceValueForFieldType(passport_entity, PASSPORT_NUMBER)); + GetEntityInstanceValue( + passport_entity, AttributeType(AttributeTypeName::kPassportNumber))); // The third field is not of AutofillAi type. EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[2]), std::nullopt); @@ -166,6 +166,8 @@ MakePassportWithRandomGuid({.name = u"Harry Potter"}); FieldType triggering_field_type = PASSPORT_NAME_TAG; + AttributeType triggering_attribute_type = + AttributeType(AttributeTypeName::kPassportName); std::unique_ptr<FormStructure> form = CreateFormStructure( {triggering_field_type, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); @@ -180,8 +182,8 @@ // Note that there is one separator and one footer suggestion as well. EXPECT_EQ(suggestions.size(), 3u); EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValueForFieldType(passport_prefix_matches, - triggering_field_type)); + GetEntityInstanceValue(passport_prefix_matches, + triggering_attribute_type)); } // Tests that no prefix matching is performed if the attribute that would be @@ -207,6 +209,8 @@ std::vector<EntityInstance> entities = {passport_entity}; FieldType triggering_field_type = PASSPORT_NAME_TAG; + AttributeType triggering_attribute_type = + AttributeType(AttributeTypeName::kPassportName); std::unique_ptr<FormStructure> form = CreateFormStructure({triggering_field_type, PASSPORT_NUMBER}); // Assign different sections to the fields. @@ -222,16 +226,14 @@ // value for the `triggering_field_type`. EXPECT_THAT(suggestions, SizeIs(Ge(1))); EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValueForFieldType(passport_entity, - triggering_field_type)); + GetEntityInstanceValue(passport_entity, triggering_attribute_type)); const Suggestion::AutofillAiPayload* payload = std::get_if<Suggestion::AutofillAiPayload>(&suggestions[0].payload); ASSERT_TRUE(payload); // The triggering/first field is of AutofillAi Type. EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[0]), - GetEntityInstanceValueForFieldType(passport_entity, - triggering_field_type)); + GetEntityInstanceValue(passport_entity, triggering_attribute_type)); } TEST_F(AutofillAiSuggestionsTest, NonMatchingEntity_DoNoReturnSuggestions) { @@ -294,6 +296,8 @@ passport_a_without_an_expiry_date}; FieldType triggering_field_type = PASSPORT_NAME_TAG; + AttributeType triggering_attribute_type = + AttributeType(AttributeTypeName::kPassportName); std::unique_ptr<FormStructure> form = CreateFormStructure( {triggering_field_type, PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY}); std::vector<Suggestion> suggestions = CreateFillingSuggestions( @@ -307,11 +311,10 @@ // proper subset of `passport`. ASSERT_THAT(suggestions, SizeIs(Ge(2))); EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValueForFieldType(another_persons_passport, - triggering_field_type)); - EXPECT_EQ( - suggestions[1].main_text.value, - GetEntityInstanceValueForFieldType(passport, triggering_field_type)); + GetEntityInstanceValue(another_persons_passport, + triggering_attribute_type)); + EXPECT_EQ(suggestions[1].main_text.value, + GetEntityInstanceValue(passport, triggering_attribute_type)); } // Tests that an "Undo Autofill" suggestion is appended if the trigger field
diff --git a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger.cc b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger.cc index 8cfeac6..c605e8dda 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger.cc
@@ -14,6 +14,7 @@ #include "base/strings/stringprintf.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/data_model/autofill_ai/entity_type.h" +#include "components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.h" #include "components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.h" #include "components/autofill/core/common/unique_ids.h" @@ -140,10 +141,10 @@ void AutofillAiLogger::RecordKeyMetrics(const FormStructure& form, const FunnelState& funnel_state) const { const std::string_view entity_type = [&] { - for (const std::unique_ptr<AutofillField>& field : form) { - if (std::optional<FieldType> ai_type = - field->GetAutofillAiServerTypePredictions()) { - switch (AttributeType::FromFieldType(*ai_type)->entity_type().name()) { + for (const auto& [section, entities_and_fields] : + DetermineAttributeTypes(form.fields())) { + for (const auto& [entity, fields_and_types] : entities_and_fields) { + switch (entity.name()) { case EntityTypeName::kPassport: return "Passport"; case EntityTypeName::kDriversLicense:
diff --git a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger_unittest.cc b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger_unittest.cc index 917d009..c7dfeb46 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger_unittest.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_logger_unittest.cc
@@ -16,6 +16,7 @@ #include "components/autofill/core/browser/data_manager/autofill_ai/entity_data_manager.h" #include "components/autofill/core/browser/data_model/autofill_ai/entity_instance.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/filling/filling_product.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/form_structure_test_api.h" #include "components/autofill/core/browser/foundations/test_autofill_client.h" @@ -135,8 +136,10 @@ form_description.fields.emplace_back( test::FieldDescription({.role = field_type})); } - auto form_structure = - std::make_unique<FormStructure>(test::GetFormData(form_description)); + FormData form_data = test::GetFormData(form_description); + form_data.set_main_frame_origin( + url::Origin::Create(GURL("https://myform_root.com/form.html"))); + auto form_structure = std::make_unique<FormStructure>(form_data); for (size_t i = 0; i < form_structure->field_count(); i++) { AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction prediction; @@ -578,23 +581,6 @@ << event; } - void ExpectCorrectMqlsKeyMetricsLogging( - const optimization_guide::proto::AutofillAiKeyMetrics& mqls_key_metrics, - const FormStructure& form, - bool filling_readiness, - bool filling_assistance, - bool filling_acceptance, - bool filling_correctness) { - EXPECT_EQ(mqls_key_metrics.domain(), "myform_root.com"); - EXPECT_EQ(mqls_key_metrics.form_signature(), form.form_signature().value()); - EXPECT_EQ(mqls_key_metrics.form_session_identifier(), - autofill_metrics::FormGlobalIdToHash64Bit(form.global_id())); - EXPECT_EQ(mqls_key_metrics.filling_readiness(), filling_readiness); - EXPECT_EQ(mqls_key_metrics.filling_assistance(), filling_assistance); - EXPECT_EQ(mqls_key_metrics.filling_acceptance(), filling_acceptance); - EXPECT_EQ(mqls_key_metrics.filling_correctness(), filling_correctness); - } - private: TestingPrefServiceSimple local_state_; std::unique_ptr<optimization_guide::TestModelQualityLogsUploaderService> @@ -635,13 +621,21 @@ } TEST_F(AutofillAiMqlsMetricsTest, KeyMetrics) { - std::unique_ptr<FormStructure> form = CreateEligibleForm(); + std::unique_ptr<FormStructure> form = CreatePassportForm(); test_api(manager()).logger().OnFormHasDataToFill(form->global_id()); test_api(manager()).logger().OnSuggestionsShown(*form, *form->field(0), /*ukm_source_id=*/{}); + form->field(0)->set_is_autofilled(true); + form->field(0)->set_filling_product(FillingProduct::kAddress); + form->field(1)->set_is_autofilled(true); + form->field(1)->set_filling_product(FillingProduct::kAutofillAi); + form->field(2)->set_is_autofilled(true); + form->field(2)->set_filling_product(FillingProduct::kAutocomplete); + test_api(manager()).logger().OnDidFillSuggestion(*form, *form->field(0), /*ukm_source_id=*/{}); + test_api(manager()).logger().OnEditedAutofilledField(*form, *form->field(0), /*ukm_source_id=*/{}); @@ -649,10 +643,19 @@ /*submission_state=*/true, /*opt_in_status=*/true); ASSERT_EQ(mqls_logs().size(), 4u); - ExpectCorrectMqlsKeyMetricsLogging( - GetKeyMetricsLogs(), *form, /*filling_readiness=*/true, - /*filling_assistance=*/true, - /*filling_acceptance=*/true, /*filling_correctness=*/false); + const optimization_guide::proto::AutofillAiKeyMetrics& mqls_key_metrics = + GetKeyMetricsLogs(); + + EXPECT_EQ(mqls_key_metrics.domain(), "myform_root.com"); + EXPECT_EQ(mqls_key_metrics.form_signature(), form->form_signature().value()); + EXPECT_EQ(mqls_key_metrics.form_session_identifier(), + autofill_metrics::FormGlobalIdToHash64Bit(form->global_id())); + EXPECT_TRUE(mqls_key_metrics.filling_readiness()); + EXPECT_TRUE(mqls_key_metrics.filling_assistance()); + EXPECT_TRUE(mqls_key_metrics.filling_acceptance()); + EXPECT_FALSE(mqls_key_metrics.filling_correctness()); + EXPECT_EQ(mqls_key_metrics.autofill_filled_field_count(), 2); + EXPECT_EQ(mqls_key_metrics.autofill_ai_filled_field_count(), 1); } // Tests that KeyMetrics MQLS metrics aren't recorded if the user is not opted
diff --git a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.cc b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.cc index 01d9647c..2a429e46 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.cc
@@ -4,6 +4,7 @@ #include "components/autofill/core/browser/integrators/autofill_ai/metrics/autofill_ai_ukm_logger.h" +#include <algorithm> #include <cstdint> #include <type_traits> @@ -12,6 +13,7 @@ #include "base/types/cxx23_to_underlying.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/filling/filling_product.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h" @@ -111,6 +113,29 @@ bool suggestion_filled, bool edited_autofilled_field, bool opt_in_status) { + const int autofill_filled_field_count = std::ranges::count_if( + form, [&](const std::unique_ptr<AutofillField>& field) { + switch (field->filling_product()) { + case FillingProduct::kAddress: + case FillingProduct::kCreditCard: + case FillingProduct::kMerchantPromoCode: + case FillingProduct::kIban: + case FillingProduct::kPassword: + case FillingProduct::kPlusAddresses: + case FillingProduct::kAutofillAi: + case FillingProduct::kLoyaltyCard: + case FillingProduct::kIdentityCredential: + return true; + case FillingProduct::kAutocomplete: + case FillingProduct::kCompose: + case FillingProduct::kDataList: + case FillingProduct::kNone: + return false; + } + }); + const int autofill_ai_filled_field_count = std::ranges::count( + form, FillingProduct::kAutofillAi, &AutofillField::filling_product); + if (optimization_guide::ModelQualityLogsUploaderService* uploader_ = client_->GetMqlsUploadService(); uploader_ && @@ -132,6 +157,10 @@ mqls_key_metrics->set_form_signature(form.form_signature().value()); mqls_key_metrics->set_form_session_identifier( autofill_metrics::FormGlobalIdToHash64Bit(form.global_id())); + mqls_key_metrics->set_autofill_filled_field_count( + autofill_filled_field_count); + mqls_key_metrics->set_autofill_ai_filled_field_count( + autofill_ai_filled_field_count); mqls_key_metrics->set_filling_readiness(data_to_fill_available); mqls_key_metrics->set_filling_assistance(suggestion_filled); if (suggestions_shown) { @@ -152,7 +181,9 @@ autofill_metrics::FormGlobalIdToHash64Bit(form.global_id())) .SetFillingReadiness(data_to_fill_available) .SetFillingAssistance(suggestion_filled) - .SetOptInStatus(opt_in_status); + .SetOptInStatus(opt_in_status) + .SetAutofillFilledFieldCount(autofill_filled_field_count) + .SetAutofillAiFilledFieldCount(autofill_ai_filled_field_count); if (suggestions_shown) { builder.SetFillingAcceptance(suggestion_filled); }
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher.cc b/components/autofill/core/browser/ui/autofill_image_fetcher.cc index 31e447b..af7599ed 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher.cc +++ b/components/autofill/core/browser/ui/autofill_image_fetcher.cc
@@ -123,7 +123,7 @@ case ImageType::kPixAccountImage: NOTREACHED() << "Pix account images are available only on Android"; case ImageType::kValuableImage: - return image; + return ResolveValuableImage(image); } }
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher.h b/components/autofill/core/browser/ui/autofill_image_fetcher.h index 681bf6c..2948af6 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher.h +++ b/components/autofill/core/browser/ui/autofill_image_fetcher.h
@@ -89,6 +89,9 @@ // resolving via `ResolveImageURL`. virtual gfx::Image ResolveCardArtImage(const GURL& card_art_url, const gfx::Image& card_art_image) = 0; + // Subclasses may override this to provide custom handling of a fetched + // valuable image. + virtual gfx::Image ResolveValuableImage(const gfx::Image& valuable_image) = 0; private: void FetchImageForURL(const GURL& image_url, ImageType image_type);
diff --git a/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc b/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc index 0210f91..1f3eb05b 100644 --- a/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc +++ b/components/autofill/core/browser/ui/autofill_image_fetcher_unittest.cc
@@ -77,6 +77,10 @@ : card_art_image; } + gfx::Image ResolveValuableImage(const gfx::Image& valuable_image) override { + return valuable_image; + } + private: gfx::Image card_art_image_override_;
diff --git a/components/browser_ui/desktop_windowing/android/java/src/org/chromium/components/browser_ui/desktop_windowing/DesktopWindowStateManager.java b/components/browser_ui/desktop_windowing/android/java/src/org/chromium/components/browser_ui/desktop_windowing/DesktopWindowStateManager.java index f121bfbbc..8fdd546b 100644 --- a/components/browser_ui/desktop_windowing/android/java/src/org/chromium/components/browser_ui/desktop_windowing/DesktopWindowStateManager.java +++ b/components/browser_ui/desktop_windowing/android/java/src/org/chromium/components/browser_ui/desktop_windowing/DesktopWindowStateManager.java
@@ -30,6 +30,15 @@ * mode. */ default void onDesktopWindowingModeChanged(boolean isInDesktopWindow) {} + + /** + * Called when the activity focus state changes. See {@link + * Activity#onTopResumedActivityChanged(boolean)}. + * + * @param isFocused Whether the activity is in a focused state. {@code true} when the + * activity is focused, {@code false} when the activity is unfocused. + */ + default void onActivityFocusStateChanged(boolean isFocused) {} } /**
diff --git a/components/browsing_data_strings.grdp b/components/browsing_data_strings.grdp index 38cf2b82..204aeb68 100644 --- a/components/browsing_data_strings.grdp +++ b/components/browsing_data_strings.grdp
@@ -172,8 +172,8 @@ <message name="IDS_DEL_COOKIES_COUNTER_ADVANCED" desc="A counter showing the number of sites that use cookies."> {COUNT, plural, =0 {None} - =1 {From 1 site } - other {From # sites }} + =1 {From 1 site} + other {From # sites}} </message> <message name="IDS_DEL_COOKIES_COUNTER_ADVANCED_WITH_SIGNED_IN_EXCEPTION" desc="A counter showing the number of sites that use cookies, followed by an exception message that the user will stay signed in to their Google account."> {COUNT, plural, @@ -224,4 +224,7 @@ <message name="IDS_DEL_TABS_MULTIWINDOW_COUNTER" desc="A counter showing how many tabs the user opened or modified across multiple windows."> <ph name="TAB_COUNT">$1<ex>5 tabs</ex></ph> from <ph name="WINDOW_COUNT">$2<ex>2 windows</ex></ph> on this device </message> + <message name="IDS_DEL_GOOGLE_COOKIES_SIGNOUT_LINK" desc="A message that will be appended to IDS_DEL_COOKIES_COUNTER_ADVANCED if the user is signed in. It informs the user that their Google cookies will only be deleted if they signed out of Chrome. This string includes a link that, when clicked on, will sign the user out of Chrome."> + To delete Google cookies from this device, <ph name="BEGIN_LINK"><a href="#" target="_blank" id="signOutLink"></ph>sign out of Chrome<ph name="END_LINK"></a></ph>. + </message> </grit-part>
diff --git a/components/browsing_data_strings_grdp/IDS_DEL_COOKIES_COUNTER_ADVANCED.png.sha1 b/components/browsing_data_strings_grdp/IDS_DEL_COOKIES_COUNTER_ADVANCED.png.sha1 new file mode 100644 index 0000000..09614b4 --- /dev/null +++ b/components/browsing_data_strings_grdp/IDS_DEL_COOKIES_COUNTER_ADVANCED.png.sha1
@@ -0,0 +1 @@ +26a159f3bf9965286502f907af64702909da0ac3 \ No newline at end of file
diff --git a/components/browsing_data_strings_grdp/IDS_DEL_GOOGLE_COOKIES_SIGNOUT_LINK.png.sha1 b/components/browsing_data_strings_grdp/IDS_DEL_GOOGLE_COOKIES_SIGNOUT_LINK.png.sha1 new file mode 100644 index 0000000..3572e86 --- /dev/null +++ b/components/browsing_data_strings_grdp/IDS_DEL_GOOGLE_COOKIES_SIGNOUT_LINK.png.sha1
@@ -0,0 +1 @@ +58c4b4c3a9ba8dafbcf65d303eb3ed225d163c20 \ No newline at end of file
diff --git a/components/collaboration/internal/messaging/instant_message_processor_impl.cc b/components/collaboration/internal/messaging/instant_message_processor_impl.cc index e22cc63..615e20e1 100644 --- a/components/collaboration/internal/messaging/instant_message_processor_impl.cc +++ b/components/collaboration/internal/messaging/instant_message_processor_impl.cc
@@ -53,7 +53,6 @@ switch (message.collaboration_event) { case CollaborationEvent::TAB_UPDATED: case CollaborationEvent::TAB_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: return false; case CollaborationEvent::TAB_GROUP_REMOVED: case CollaborationEvent::COLLABORATION_MEMBER_ADDED:
diff --git a/components/collaboration/internal/messaging/messaging_backend_service_impl.cc b/components/collaboration/internal/messaging/messaging_backend_service_impl.cc index 4b0a3c7..c7c9cfb6 100644 --- a/components/collaboration/internal/messaging/messaging_backend_service_impl.cc +++ b/components/collaboration/internal/messaging/messaging_backend_service_impl.cc
@@ -171,8 +171,6 @@ return CollaborationEvent::COLLABORATION_MEMBER_ADDED; case collaboration_pb::COLLABORATION_MEMBER_REMOVED: return CollaborationEvent::COLLABORATION_MEMBER_REMOVED; - case collaboration_pb::VERSION_OUT_OF_DATE: - return CollaborationEvent::VERSION_OUT_OF_DATE; default: return CollaborationEvent::UNDEFINED; } @@ -198,8 +196,6 @@ case CollaborationEvent::COLLABORATION_MEMBER_ADDED: case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: return RecentActivityAction::kManageSharing; - case CollaborationEvent::VERSION_OUT_OF_DATE: - return RecentActivityAction::kNone; case CollaborationEvent::UNDEFINED: return RecentActivityAction::kNone; } @@ -1321,7 +1317,6 @@ case CollaborationEvent::TAB_GROUP_REMOVED: case CollaborationEvent::COLLABORATION_ADDED: case CollaborationEvent::COLLABORATION_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: case CollaborationEvent::UNDEFINED: CHECK(false) << "No string res for collaboration event " << static_cast<size_t>(collaboration_event);
diff --git a/components/collaboration/public/messaging/message.h b/components/collaboration/public/messaging/message.h index 328a2cb..f68828a 100644 --- a/components/collaboration/public/messaging/message.h +++ b/components/collaboration/public/messaging/message.h
@@ -41,9 +41,6 @@ // Deprecated: Migrated to TAB_GROUP_REMOVED instead. Current user left or // lost access. COLLABORATION_REMOVED, - - // Source: Finch. - VERSION_OUT_OF_DATE, }; // Different types of instant notifications that need to be shown immediately
diff --git a/components/credential_management/content_credential_manager.cc b/components/credential_management/content_credential_manager.cc index dff96f68..c29c97a 100644 --- a/components/credential_management/content_credential_manager.cc +++ b/components/credential_management/content_credential_manager.cc
@@ -13,6 +13,16 @@ #include "content/public/browser/web_contents.h" #include "mojo/public/cpp/bindings/message.h" +namespace { +void LogGetCredentialsMetrics( + credential_management::ContentCredentialManager::GetCallback callback, + password_manager::CredentialManagerError error, + const std::optional<password_manager::CredentialInfo>& info) { + password_manager::metrics_util::LogCumulativeGetCredentialsMetrics(error); + std::move(callback).Run(error, info); +} +} // namespace + namespace credential_management { // ContentCredentialManager ------------------------------------------------- @@ -102,8 +112,9 @@ bool include_passwords, const std::vector<GURL>& federations, GetCallback callback) { - credential_manager_->Get(mediation, include_passwords, federations, - std::move(callback)); + credential_manager_->Get( + mediation, include_passwords, federations, + base::BindOnce(&LogGetCredentialsMetrics, std::move(callback))); } } // namespace credential_management
diff --git a/components/enterprise/connectors/core/reporting_event_router.cc b/components/enterprise/connectors/core/reporting_event_router.cc index afde0d67..6e68e4a 100644 --- a/components/enterprise/connectors/core/reporting_event_router.cc +++ b/components/enterprise/connectors/core/reporting_event_router.cc
@@ -209,25 +209,39 @@ return; } - base::Value::Dict event; - event.Set(kKeyUrl, url.spec()); - EventResult event_result = GetEventResultFromThreatType(threat_type); - event.Set(kKeyClickedThrough, - event_result == enterprise_connectors::EventResult::BYPASSED); - if (!threat_type.empty()) { - event.Set(kKeyThreatType, threat_type); - } - AddTriggeredRuleInfoToUrlFilteringInterstitialEvent(response, event); - event.Set(kKeyEventResult, - enterprise_connectors::EventResultToString(event_result)); + if (base::FeatureList::IsEnabled( + policy::kUploadRealtimeReportingEventsUsingProto)) { + chrome::cros::reporting::proto::Event event; + *event.mutable_url_filtering_interstitial_event() = + GetUrlFilteringInterstitialEvent( + url, threat_type, response, + reporting_client_->GetProfileIdentifier(), + reporting_client_->GetProfileUserName(), referrer_chain); + *event.mutable_time() = ToProtoTimestamp(base::Time::Now()); - if (base::FeatureList::IsEnabled(safe_browsing::kEnhancedFieldsForSecOps)) { - AddReferrerChainToEvent(referrer_chain, event); - } + reporting_client_->ReportEvent(std::move(event), settings.value()); + } else { + base::Value::Dict event; + event.Set(kKeyUrl, url.spec()); + EventResult event_result = GetEventResultFromThreatType(threat_type); + event.Set(kKeyClickedThrough, + event_result == enterprise_connectors::EventResult::BYPASSED); + if (!threat_type.empty()) { + event.Set(kKeyThreatType, threat_type); + } + AddTriggeredRuleInfoToUrlFilteringInterstitialEvent(response, event); + event.Set(kKeyEventResult, + enterprise_connectors::EventResultToString(event_result)); - reporting_client_->ReportEventWithTimestampDeprecated( - kKeyUrlFilteringInterstitialEvent, std::move(settings.value()), - std::move(event), base::Time::Now(), /*include_profile_user_name=*/true); + if (base::FeatureList::IsEnabled(safe_browsing::kEnhancedFieldsForSecOps)) { + AddReferrerChainToEvent(referrer_chain, event); + } + + reporting_client_->ReportEventWithTimestampDeprecated( + kKeyUrlFilteringInterstitialEvent, std::move(settings.value()), + std::move(event), base::Time::Now(), + /*include_profile_user_name=*/true); + } } void ReportingEventRouter::OnSecurityInterstitialProceeded(
diff --git a/components/enterprise/connectors/core/reporting_test_utils.cc b/components/enterprise/connectors/core/reporting_test_utils.cc index 4ca4eb60..338ecdd 100644 --- a/components/enterprise/connectors/core/reporting_test_utils.cc +++ b/components/enterprise/connectors/core/reporting_test_utils.cc
@@ -201,6 +201,30 @@ } } +void EventReportValidatorBase::ExpectProtoBasedUrlFilteringInterstitialEvent( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent + expected_urlf_event) { + EXPECT_CALL(*client_, UploadSecurityEvent) + .WillOnce( + [this, expected_urlf_event]( + bool include_device_info, + ::chrome::cros::reporting::proto::UploadEventsRequest request, + base::OnceCallback<void(policy::CloudPolicyClient::Result)> + callback) { + // There should only be 1 event per test. + ASSERT_EQ(1, request.events_size()); + ASSERT_TRUE( + request.events().Get(0).has_url_filtering_interstitial_event()); + auto urlf_event = + request.events().Get(0).url_filtering_interstitial_event(); + EXPECT_THAT(urlf_event, EqualsProto(expected_urlf_event)); + + if (!done_closure_.is_null()) { + done_closure_.Run(); + } + }); +} + void EventReportValidatorBase::ExpectURLFilteringInterstitialEvent( chrome::cros::reporting::proto::UrlFilteringInterstitialEvent expected_urlf_event) {
diff --git a/components/enterprise/connectors/core/reporting_test_utils.h b/components/enterprise/connectors/core/reporting_test_utils.h index 06bbf50..5bb0e7d 100644 --- a/components/enterprise/connectors/core/reporting_test_utils.h +++ b/components/enterprise/connectors/core/reporting_test_utils.h
@@ -34,11 +34,19 @@ void ExpectNoReport(); + // TODO(crbug.com/396439420): Rename this method and delete the other two url + // filtering event validation methods + void ExpectProtoBasedUrlFilteringInterstitialEvent( + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent + expected_urlf_event); + void ExpectURLFilteringInterstitialEvent( - chrome::cros::reporting::proto::UrlFilteringInterstitialEvent event); + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent + expected_urlf_event); void ExpectURLFilteringInterstitialEventWithReferrers( - chrome::cros::reporting::proto::UrlFilteringInterstitialEvent event); + chrome::cros::reporting::proto::UrlFilteringInterstitialEvent + expected_urlf_event); // TODO(crbug.com/396438091): Delete this method once proto migration is // complete.
diff --git a/components/enterprise/watermarking/watermark.cc b/components/enterprise/watermarking/watermark.cc index 9a311600..3b7693d4 100644 --- a/components/enterprise/watermarking/watermark.cc +++ b/components/enterprise/watermarking/watermark.cc
@@ -62,6 +62,7 @@ render_text->SetFontList(WatermarkFontList()); render_text->SetWeight(WatermarkFontWeight()); render_text->SetDisplayOffset(gfx::Vector2d(0, 0)); + render_text->SetVerticalAlignment(gfx::VerticalAlignment::ALIGN_TOP); render_text->SetDisplayRect(display_rect); render_text->SetText(text); render_text->SetMultiline(true); @@ -132,12 +133,6 @@ return cos(angle) * bounds.width() + block_width_offset(block_width); } -int min_y(double angle, const SkSize& bounds) { - // Instead of starting at Y=0, starting at `kTextSize` lets the first line of - // text be in frame as text is drawn with (0,0) as the bottom-left corner. - return kTextSize; -} - int max_y(double angle, const SkSize& bounds) { // Due to the rotation of the watermark, Y needs to end further then the // `bounds` height. This means our final Y needs to be proportional to these @@ -246,8 +241,11 @@ for (int x = min_x(kRotationAngle, contents_bounds, block_width); x <= upper_x; x += block_width_offset(block_width)) { bool apply_stagger = false; - for (int y = min_y(kRotationAngle, contents_bounds); y < upper_y; - y += block_height_offset(block_height)) { + + // The vertical alignment of the watermark's RenderText is set to + // ALIGN_TOP. Starting at Y=0 with this setting aligns the top edge of the + // text with the top edge of the contents area. + for (int y = 0; y < upper_y; y += block_height_offset(block_height)) { // Every other row, stagger the text horizontally to give a // "brick tiling" effect. int stagger = apply_stagger ? block_width_offset(block_width) / 2 : 0;
diff --git a/components/feature_engagement/public/event_constants.cc b/components/feature_engagement/public/event_constants.cc index e3d75c5..d789807 100644 --- a/components/feature_engagement/public/event_constants.cc +++ b/components/feature_engagement/public/event_constants.cc
@@ -173,6 +173,7 @@ "ios_safari_import_entry_point_remind_me_later"; const char kIOSPageActionMenuIPHTrigger[] = "page_action_menu_iph_trigger"; const char kIOSPageActionMenuIPHUsed[] = "page_action_menu_iph_used"; +const char kIOSFirstRunComplete[] = "ios_first_run_complete"; #endif // BUILDFLAG(IS_IOS) #if BUILDFLAG(IS_ANDROID)
diff --git a/components/feature_engagement/public/event_constants.h b/components/feature_engagement/public/event_constants.h index 746fc2a..91636fb8 100644 --- a/components/feature_engagement/public/event_constants.h +++ b/components/feature_engagement/public/event_constants.h
@@ -335,6 +335,9 @@ // The entry point of the import Safari data workflow has been displayed. extern const char kIOSSafariImportRemindMeLater[]; +// Event fired when the First Run Experience (FRE) is completed on iOS. +extern const char kIOSFirstRunComplete[]; + #endif // BUILDFLAG(IS_IOS) // Android.
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc index 2aaf0ac..296547a 100644 --- a/components/lens/lens_features.cc +++ b/components/lens/lens_features.cc
@@ -41,7 +41,7 @@ BASE_FEATURE(kLensOverlayContextualSearchbox, "LensOverlayContextualSearchbox", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kLensOverlayContextualSearchboxForOmniboxSuggestions, "LensOverlayContextualSearchboxForOmniboxSuggestions",
diff --git a/components/omnibox/browser/enterprise_search_aggregator_suggestions_service_unittest.cc b/components/omnibox/browser/enterprise_search_aggregator_suggestions_service_unittest.cc index b250374..276b656 100644 --- a/components/omnibox/browser/enterprise_search_aggregator_suggestions_service_unittest.cc +++ b/components/omnibox/browser/enterprise_search_aggregator_suggestions_service_unittest.cc
@@ -5,7 +5,6 @@ #include "components/omnibox/browser/enterprise_search_aggregator_suggestions_service.h" #include "base/functional/bind.h" -#include "base/json/json_parser.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/strings/string_number_conversions.h"
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java index 12e21be8..075147f 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java
@@ -116,6 +116,11 @@ public static final CachedFlag sOmniboxMobileParityUpdate = newFlag(OmniboxFeatureList.OMNIBOX_MOBILE_PARITY_UPDATE, FeatureState.ENABLED_IN_TEST); + public static final CachedFlag sOmniboxMobileParityUpdateV2 = + newFlag( + OmniboxFeatureList.OMNIBOX_MOBILE_PARITY_UPDATE_V2, + FeatureState.ENABLED_IN_TEST); + public static final BooleanCachedFeatureParam sOmniboxParityRetrieveTrueFavicon = newBooleanParam(sOmniboxMobileParityUpdate, "retrieve_true_favicon", false);
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index b86214a..7f8a36e2 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -335,6 +335,12 @@ // Android and iOS. BASE_FEATURE(kOmniboxMobileParityUpdate, "OmniboxMobileParityUpdate", DISABLED); +// Updates various NTP/Omnibox assets and descriptions for visual alignment on +// Android and iOS, V2. +BASE_FEATURE(kOmniboxMobileParityUpdateV2, + "OmniboxMobileParityUpdateV2", + DISABLED); + // The features below allow tuning number of suggestions offered to users in // specific contexts. These features are default enabled and are used to control // related fieldtrial parameters. @@ -411,7 +417,8 @@ &kJumpStartOmnibox, &kAndroidHubSearchTabGroups, &kPostDelayedTaskFocusTab, - &kOmniboxMobileParityUpdate}; + &kOmniboxMobileParityUpdate, + &kOmniboxMobileParityUpdateV2}; static base::NoDestructor<base::android::FeatureMap> kFeatureMap( kFeaturesExposedToJava); return reinterpret_cast<jlong>(kFeatureMap.get()); @@ -433,7 +440,7 @@ // determines if the engine can be overridden on the Settings page. BASE_FEATURE(kEnableSiteSearchAllowUserOverridePolicy, "EnableSiteSearchAllowUserOverridePolicy", - DISABLED); + ENABLED); // Enables preconnecting to omnibox suggestions that are not only Search types. BASE_FEATURE(kPreconnectNonSearchOmniboxSuggestions,
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index 9729689a..b881b26 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -122,6 +122,7 @@ BASE_DECLARE_FEATURE(kUseFusedLocationProvider); BASE_DECLARE_FEATURE(kOmniboxMobileParityUpdate); +BASE_DECLARE_FEATURE(kOmniboxMobileParityUpdateV2); // Omnibox suggestions tuning BASE_DECLARE_FEATURE(kNumNtpZpsRecentSearches);
diff --git a/components/optimization_guide/core/hints/hints_manager.cc b/components/optimization_guide/core/hints/hints_manager.cc index 7517c153..dc57206 100644 --- a/components/optimization_guide/core/hints/hints_manager.cc +++ b/components/optimization_guide/core/hints/hints_manager.cc
@@ -830,8 +830,7 @@ &HintsManager::FetchHintsForActiveTabsInternal, weak_ptr_factory_.GetWeakPtr(), top_hosts, active_tab_urls_to_refresh, proto::CONTEXT_BATCH_UPDATE_ACTIVE_TABS, - /*skip_cache=*/false, std::move(hints_fetched_callback), - /*request_context_metadata=*/std::nullopt); + std::move(hints_fetched_callback)); HandleTokenRequestFlow( HasPersonalizableTypesRegistered(), identity_manager_, {GaiaConstants::kOptimizationGuideServiceGetHintsOAuth2Scope}, @@ -842,9 +841,7 @@ const std::vector<std::string>& top_hosts, const std::vector<GURL>& active_tab_urls_to_refresh, optimization_guide::proto::RequestContext request_context, - bool skip_cache, HintsFetchedCallback hints_fetched_callback, - std::optional<proto::RequestContextMetadata> request_context_metadata, const std::string& access_token) { if (!active_tabs_batch_update_hints_fetcher_) { DCHECK(hints_fetcher_factory_); @@ -1015,6 +1012,22 @@ target_urls.vector(), target_hosts.vector(), optimization_guide_logger_); + auto do_fetch_callback = base::BindOnce( + &HintsManager::FetchHintsForURLsInternal, weak_ptr_factory_.GetWeakPtr(), + target_hosts, target_urls, request_context); + HandleTokenRequestFlow( + HasPersonalizableTypesRegistered(), identity_manager_, + {GaiaConstants::kOptimizationGuideServiceGetHintsOAuth2Scope}, + base::BindOnce(&HintsManager::FetchHintsForURLsInternal, + weak_ptr_factory_.GetWeakPtr(), target_hosts, target_urls, + request_context)); +} + +void HintsManager::FetchHintsForURLsInternal( + const InsertionOrderedSet<std::string>& target_hosts, + const InsertionOrderedSet<GURL>& target_urls, + optimization_guide::proto::RequestContext request_context, + const std::string& access_token) { std::pair<int32_t, HintsFetcher*> request_id_and_fetcher = CreateAndTrackBatchUpdateHintsFetcher(); @@ -1026,7 +1039,7 @@ request_id_and_fetcher.second->FetchOptimizationGuideServiceHints( target_hosts.vector(), target_urls.vector(), registered_optimization_types_, request_context, application_locale_, - /*access_token=*/std::string(), + access_token, /*skip_cache=*/false, base::BindOnce( &HintsManager::OnBatchUpdateHintsFetched,
diff --git a/components/optimization_guide/core/hints/hints_manager.h b/components/optimization_guide/core/hints/hints_manager.h index 719a41f..1a70361 100644 --- a/components/optimization_guide/core/hints/hints_manager.h +++ b/components/optimization_guide/core/hints/hints_manager.h
@@ -596,14 +596,20 @@ base::WeakPtrFactory<HintsManager> weak_ptr_factory_{this}; // Wrapper that immediately invokes HintsFetcher for the purposes of fetching + // hints for urls. + void FetchHintsForURLsInternal( + const InsertionOrderedSet<std::string>& target_hosts, + const InsertionOrderedSet<GURL>& target_urls, + optimization_guide::proto::RequestContext request_context, + const std::string& access_token); + + // Wrapper that immediately invokes HintsFetcher for the purposes of fetching // hints for active tabs. void FetchHintsForActiveTabsInternal( const std::vector<std::string>& top_hosts, const std::vector<GURL>& active_tab_urls_to_refresh, optimization_guide::proto::RequestContext request_context, - bool skip_cache, HintsFetchedCallback hints_fetched_callback, - std::optional<proto::RequestContextMetadata> request_context_metadata, const std::string& access_token); };
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index dcfc452..9e8ee51 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit dcfc4528bdad156f1743629801618682fd9f7785 +Subproject commit 9e8ee5114eb95c9675a3ea819e20773bc26e760c
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc index 992aa80..b5b4123 100644 --- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc +++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -166,26 +166,26 @@ WebFeature::kSchemelesslySameSitePostMessage, WebFeature::kSchemelesslySameSitePostMessageSecureToInsecure, WebFeature::kSchemelesslySameSitePostMessageInsecureToSecure, - WebFeature::kAddressSpacePrivateSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePrivateNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePublicSecureContextEmbeddedPrivate, - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedPrivate, - WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLocal, - WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpaceUnknownSecureContextEmbeddedPrivate, - WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedPrivate, - WebFeature::kAddressSpacePrivateSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePrivateNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpacePublicSecureContextNavigatedToPrivate, - WebFeature::kAddressSpacePublicNonSecureContextNavigatedToPrivate, - WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLocal, - WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLocal, - WebFeature::kAddressSpaceUnknownSecureContextNavigatedToPrivate, - WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToPrivate, + WebFeature::kAddressSpaceLocalSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceUnknownSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceUnknownNonSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpaceLocalSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceLocalNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpacePublicSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2, + WebFeature::kAddressSpaceUnknownSecureContextNavigatedToLocalV2, + WebFeature::kAddressSpaceUnknownNonSecureContextNavigatedToLocalV2, WebFeature::kFileSystemPickerMethod, WebFeature::kV8Window_ShowOpenFilePicker_Method, WebFeature::kV8Window_ShowSaveFilePicker_Method,
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc index a8b955bc..69db2dc 100644 --- a/components/password_manager/core/browser/features/password_features.cc +++ b/components/password_manager/core/browser/features/password_features.cc
@@ -172,7 +172,7 @@ BASE_FEATURE(kLoginDbDeprecationAndroid, "LoginDbDeprecationAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) BASE_FEATURE(kUseNewEncryptionMethod,
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index fd6a854..5e58fa69 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -659,4 +659,11 @@ } } +void LogCumulativeGetCredentialsMetrics( + password_manager::CredentialManagerError error) { + base::UmaHistogramBoolean( + "PasswordManager.CredentialRequest.Get.Success", + error == password_manager::CredentialManagerError::SUCCESS); +} + } // namespace password_manager::metrics_util
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index cce90b9..b174cd5b 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -881,6 +881,11 @@ // match filling was available to the user. void LogFillSuggestionGroupedMatchAccepted(bool grouped_match_accepted); +// Logs the result of a navigator.credentials.get() call into an aggregated +// histogram for both Chrome and third party requests. +void LogCumulativeGetCredentialsMetrics( + password_manager::CredentialManagerError error); + } // namespace password_manager::metrics_util #endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_PASSWORD_MANAGER_METRICS_UTIL_H_
diff --git a/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc b/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc index 1aeff0c..1b0a82b7 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc
@@ -432,6 +432,50 @@ {PasswordDropdownDuplicateCredentialsType::kDuplicatePasswords}}, })); +struct CredentialManagerMetricsTestCase { + password_manager::CredentialManagerError error; + bool success; +}; + +class CredentialManagerMetricsTest + : public ::testing::TestWithParam<CredentialManagerMetricsTestCase> {}; + +TEST_P(CredentialManagerMetricsTest, LogCumulativeGetMetrics) { + base::HistogramTester histogram_tester; + const CredentialManagerMetricsTestCase& test_case = GetParam(); + + LogCumulativeGetCredentialsMetrics(/*error=*/test_case.error); + + histogram_tester.ExpectUniqueSample( + "PasswordManager.CredentialRequest.Get.Success", test_case.success, 1); +} + +INSTANTIATE_TEST_SUITE_P( + All, + CredentialManagerMetricsTest, + ::testing::ValuesIn(std::vector<CredentialManagerMetricsTestCase>{ + // Success, the expected behaviour + { + /*error=*/password_manager::CredentialManagerError::SUCCESS, + /*success=*/true, + }, + // Pending request, only applicable to 1sr party requests + { + /*error=*/password_manager::CredentialManagerError::PENDING_REQUEST, + /*success=*/false, + }, + // Password store unavailable, only applicable to 1sr party requests + { + /*error=*/password_manager::CredentialManagerError:: + PASSWORDSTOREUNAVAILABLE, + /*success=*/false, + }, + // Unknown error + { + /*error=*/password_manager::CredentialManagerError::UNKNOWN, + /*success=*/false, + }, + })); } // namespace } // namespace password_manager::metrics_util
diff --git a/components/password_manager/core/browser/password_manager_util_unittest.cc b/components/password_manager/core/browser/password_manager_util_unittest.cc index 6144b3f..b036f2b 100644 --- a/components/password_manager/core/browser/password_manager_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_util_unittest.cc
@@ -657,9 +657,13 @@ } } +// TODO(crbug.com/378653046): Merge android and non-android tests when +// kLoginDbDeprecationAndroid flag and kPasswordsUseUPMLocalAndSeparateStores +// pref are gone. Merge into 2 tests: IsAbleToSavePasswords_Syncing and +// IsAbleToSavePasswords_NotSyncing. #if BUILDFLAG(IS_ANDROID) TEST_F(PasswordManagerUtilTest, - IsAbleToSavePasswordsAfterLoginDbDeprecation_Syncing) { + IsAbleToSavePasswords_Syncing_AfterLoginDbDeprecation) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature( password_manager::features::kLoginDbDeprecationAndroid); @@ -681,10 +685,14 @@ EXPECT_CALL(*profile_store, IsAbleToSavePasswords).Times(0); EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); + + EXPECT_CALL(*account_store, IsAbleToSavePasswords).WillOnce(Return(false)); + + EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); } TEST_F(PasswordManagerUtilTest, - IsAbleToSavePasswordsAfterLoginDbDeprecation_NotSyncing) { + IsAbleToSavePasswords_NotSyncing_AfterLoginDbDeprecation) { base::test::ScopedFeatureList feature_list; feature_list.InitAndEnableFeature( password_manager::features::kLoginDbDeprecationAndroid); @@ -706,9 +714,13 @@ EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(true)); EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); + + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(false)); + + EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); } -TEST_F(PasswordManagerUtilTest, IsAbleToSavePasswordsAfterStoreSplit_Syncing) { +TEST_F(PasswordManagerUtilTest, IsAbleToSavePasswords_Syncing_AfterStoreSplit) { base::test::ScopedFeatureList feature_list; feature_list.InitAndDisableFeature( password_manager::features::kLoginDbDeprecationAndroid); @@ -716,18 +728,27 @@ password_manager::prefs::kPasswordsUseUPMLocalAndSeparateStores, 2); EnableSyncForTestAccount(); - scoped_refptr<password_manager::MockPasswordStoreInterface> store( + scoped_refptr<password_manager::MockPasswordStoreInterface> account_store( + new password_manager::MockPasswordStoreInterface); + scoped_refptr<password_manager::MockPasswordStoreInterface> profile_store( new password_manager::MockPasswordStoreInterface); EXPECT_CALL(mock_client_, GetAccountPasswordStore) - .WillRepeatedly(testing::Return(store.get())); + .WillRepeatedly(testing::Return(account_store.get())); + EXPECT_CALL(mock_client_, GetProfilePasswordStore) + .WillRepeatedly(testing::Return(profile_store.get())); - EXPECT_CALL(*store, IsAbleToSavePasswords).WillOnce(Return(true)); + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).Times(0); + EXPECT_CALL(*account_store, IsAbleToSavePasswords).WillOnce(Return(true)); EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); + + EXPECT_CALL(*account_store, IsAbleToSavePasswords).WillOnce(Return(false)); + + EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); } TEST_F(PasswordManagerUtilTest, - IsAbleToSavePasswordsAfterStoreSplit_NotSyncing) { + IsAbleToSavePasswords_NotSyncing_AfterStoreSplit) { base::test::ScopedFeatureList feature_list; feature_list.InitAndDisableFeature( password_manager::features::kLoginDbDeprecationAndroid); @@ -735,37 +756,68 @@ password_manager::prefs::kPasswordsUseUPMLocalAndSeparateStores, 2); DisableSyncFeature(); - scoped_refptr<password_manager::MockPasswordStoreInterface> store( + scoped_refptr<password_manager::MockPasswordStoreInterface> account_store( new password_manager::MockPasswordStoreInterface); + scoped_refptr<password_manager::MockPasswordStoreInterface> profile_store( + new password_manager::MockPasswordStoreInterface); + EXPECT_CALL(mock_client_, GetAccountPasswordStore) + .WillRepeatedly(testing::Return(account_store.get())); EXPECT_CALL(mock_client_, GetProfilePasswordStore) - .WillRepeatedly(testing::Return(store.get())); + .WillRepeatedly(testing::Return(profile_store.get())); - EXPECT_CALL(*store, IsAbleToSavePasswords).WillOnce(Return(true)); + EXPECT_CALL(*account_store, IsAbleToSavePasswords).Times(0); + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(true)); EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); -} -#endif -TEST_F(PasswordManagerUtilTest, IsAbleToSavePasswords) { - scoped_refptr<password_manager::MockPasswordStoreInterface> store( - new password_manager::MockPasswordStoreInterface); - EXPECT_CALL(mock_client_, GetProfilePasswordStore) - .WillRepeatedly(testing::Return(store.get())); - - EXPECT_CALL(*store, IsAbleToSavePasswords).WillOnce(Return(true)); - - EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); -} - -TEST_F(PasswordManagerUtilTest, IsNotAbleToSavePasswords) { - scoped_refptr<password_manager::MockPasswordStoreInterface> store( - new password_manager::MockPasswordStoreInterface); - EXPECT_CALL(mock_client_, GetProfilePasswordStore) - .WillRepeatedly(testing::Return(store.get())); - - EXPECT_CALL(*store, IsAbleToSavePasswords).WillOnce(Return(false)); + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(false)); EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); } +#else // BUILDFLAG(IS_ANDROID) +TEST_F(PasswordManagerUtilTest, IsAbleToSavePasswords_Syncing) { + EnableSyncForTestAccount(); + + scoped_refptr<password_manager::MockPasswordStoreInterface> account_store( + new password_manager::MockPasswordStoreInterface); + scoped_refptr<password_manager::MockPasswordStoreInterface> profile_store( + new password_manager::MockPasswordStoreInterface); + EXPECT_CALL(mock_client_, GetAccountPasswordStore) + .WillRepeatedly(testing::Return(account_store.get())); + EXPECT_CALL(mock_client_, GetProfilePasswordStore) + .WillRepeatedly(testing::Return(profile_store.get())); + + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(true)); + EXPECT_CALL(*account_store, IsAbleToSavePasswords).Times(0); + + EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); + + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(false)); + + EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); +} + +TEST_F(PasswordManagerUtilTest, IsAbleToSavePasswords_NotSyncing) { + DisableSyncFeature(); + + scoped_refptr<password_manager::MockPasswordStoreInterface> account_store( + new password_manager::MockPasswordStoreInterface); + scoped_refptr<password_manager::MockPasswordStoreInterface> profile_store( + new password_manager::MockPasswordStoreInterface); + EXPECT_CALL(mock_client_, GetAccountPasswordStore) + .WillRepeatedly(testing::Return(account_store.get())); + EXPECT_CALL(mock_client_, GetProfilePasswordStore) + .WillRepeatedly(testing::Return(profile_store.get())); + + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(true)); + EXPECT_CALL(*account_store, IsAbleToSavePasswords).Times(0); + + EXPECT_TRUE(IsAbleToSavePasswords(&mock_client_)); + + EXPECT_CALL(*profile_store, IsAbleToSavePasswords).WillOnce(Return(false)); + + EXPECT_FALSE(IsAbleToSavePasswords(&mock_client_)); +} +#endif // BUILDFLAG(IS_ANDROID) } // namespace password_manager_util
diff --git a/components/payments/content/BUILD.gn b/components/payments/content/BUILD.gn index 930f725..42a95fb 100644 --- a/components/payments/content/BUILD.gn +++ b/components/payments/content/BUILD.gn
@@ -53,6 +53,7 @@ "secure_payment_confirmation_service.h", "secure_payment_confirmation_service_factory.cc", "secure_payment_confirmation_service_factory.h", + "secure_payment_confirmation_transaction_mode.h", "secure_payment_confirmation_view.h", "service_worker_payment_app.cc", "service_worker_payment_app.h",
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn index 848e048..0b7f532b 100644 --- a/components/payments/content/android/BUILD.gn +++ b/components/payments/content/android/BUILD.gn
@@ -280,6 +280,7 @@ ":method_strings_generated_srcjar", ":minimal_jni", ":payment_app_type_generated_enum", + ":spc_transaction_mode_generated_enum", ] resources_package = "org.chromium.components.payments" } @@ -330,6 +331,10 @@ sources = [ "//components/payments/core/journey_logger.h" ] } +java_cpp_enum("spc_transaction_mode_generated_enum") { + sources = [ "//components/payments/content/secure_payment_confirmation_transaction_mode.h" ] +} + robolectric_library("junit_test_support") { sources = [ "junit/src/org/chromium/components/payments/test_support/DefaultPaymentFeatureConfig.java",
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestWebContentsData.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestWebContentsData.java index 656601c..81e1b860 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestWebContentsData.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestWebContentsData.java
@@ -74,11 +74,21 @@ PaymentRequestWebContentsDataJni.get().recordActivationlessShow(webContents); } + public @SPCTransactionMode int getSPCTransactionMode() { + WebContents webContents = getWebContents(); + if (webContents == null || webContents.isDestroyed()) { + return SPCTransactionMode.NONE; + } + return PaymentRequestWebContentsDataJni.get().getSPCTransactionMode(webContents); + } + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @NativeMethods public interface Natives { boolean hadActivationlessShow(WebContents webContents); void recordActivationlessShow(WebContents webContents); + + int getSPCTransactionMode(WebContents webContents); } }
diff --git a/components/payments/content/android/payment_request_web_contents_data_android.cc b/components/payments/content/android/payment_request_web_contents_data_android.cc index bfe8260..62f7e30 100644 --- a/components/payments/content/android/payment_request_web_contents_data_android.cc +++ b/components/payments/content/android/payment_request_web_contents_data_android.cc
@@ -4,6 +4,7 @@ #include "base/android/jni_android.h" #include "components/payments/content/payment_request_web_contents_manager.h" +#include "components/payments/content/secure_payment_confirmation_transaction_mode.h" #include "content/public/browser/web_contents.h" // Must come after all headers that specialize FromJniType() / ToJniType(). @@ -18,7 +19,7 @@ const base::android::JavaParamRef<jobject>& jweb_contents) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); - DCHECK(web_contents); + CHECK(web_contents); return PaymentRequestWebContentsManager::GetOrCreateForWebContents( web_contents) @@ -31,11 +32,24 @@ const base::android::JavaParamRef<jobject>& jweb_contents) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); - DCHECK(web_contents); + CHECK(web_contents); PaymentRequestWebContentsManager::GetOrCreateForWebContents(web_contents) ->RecordActivationlessShow(); } +// static +jint JNI_PaymentRequestWebContentsData_GetSPCTransactionMode( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& jweb_contents) { + content::WebContents* web_contents = + content::WebContents::FromJavaWebContents(jweb_contents); + CHECK(web_contents); + + return static_cast<jint>( + PaymentRequestWebContentsManager::GetOrCreateForWebContents(web_contents) + ->transaction_mode()); +} + } // namespace android } // namespace payments
diff --git a/components/payments/content/android/spc/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationController.java b/components/payments/content/android/spc/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationController.java index 9d6c5179..9895dd7 100644 --- a/components/payments/content/android/spc/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationController.java +++ b/components/payments/content/android/spc/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationController.java
@@ -22,6 +22,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; import org.chromium.components.payments.PaymentApp.PaymentEntityLogo; import org.chromium.components.payments.R; +import org.chromium.components.payments.SPCTransactionMode; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationBottomSheetObserver.ControllerDelegate; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationProperties.ItemProperties; import org.chromium.components.payments.ui.CurrencyFormatter; @@ -79,8 +80,9 @@ private final SecurePaymentConfirmationView mView; private final PropertyModel mModel; private final BottomSheetController mBottomSheetController; - private final Callback<Integer> mResponseCallback; private final Boolean mInformOnly; + private final Callback<Integer> mResponseCallback; + private final @SPCTransactionMode int mTransactionMode; private SecurePaymentConfirmationBottomSheetObserver mBottomSheetObserver; private InputProtector mInputProtector = new InputProtector(); @@ -99,6 +101,7 @@ * @param showOptOut Whether to show the opt out UX to the user. * @param informOnly Whether to show the inform-only UX. * @param responseCallback The function to call on sheet dismiss; called with SpcResponseStatus. + * @param transactionMode The automation transaction mode; NONE when not under automation. */ public SecurePaymentConfirmationController( WindowAndroid window, @@ -112,7 +115,8 @@ String relyingPartyId, boolean showOptOut, boolean informOnly, - Callback<Integer> responseCallback) { + Callback<Integer> responseCallback, + @SPCTransactionMode int transactionMode) { Context context = assertNonNull(window.getContext().get()); BottomSheetController bottomSheetController = assertNonNull(BottomSheetControllerProvider.from(window)); @@ -120,6 +124,7 @@ mBottomSheetController = bottomSheetController; mInformOnly = informOnly; mResponseCallback = responseCallback; + mTransactionMode = transactionMode; mInputProtector.markShowTime(); ModelList itemList = new ModelList(); @@ -289,6 +294,25 @@ public boolean show() { if (mBottomSheetController.requestShowContent(mContent, /* animate= */ true)) { mBottomSheetObserver.begin(this); + + // For browser automation use-cases (such as WebDriver), SPC can be placed in + // transaction mode where it will immediately take some action on the dialog without + // user interaction. We deliberately wait until after the dialog is created and shown + // to handle this, in order to keep the automation codepath close to the real one. + // + // https://w3c.github.io/secure-payment-confirmation/#sctn-transaction-ux-test-automation + switch (mTransactionMode) { + case SPCTransactionMode.AUTOACCEPT: + onContinue(); + break; + case SPCTransactionMode.AUTOOPTOUT: + onOptOut(); + break; + case SPCTransactionMode.AUTOREJECT: + onCancel(); + break; + } + return true; } return false; @@ -301,7 +325,11 @@ } private void onContinue() { - if (!mInputProtector.shouldInputBeProcessed()) return; + if (!mInputProtector.shouldInputBeProcessed() + && mTransactionMode == SPCTransactionMode.NONE) { + return; + } + hide(); if (mInformOnly) { mResponseCallback.onResult(SpcResponseStatus.ANOTHER_WAY); @@ -312,19 +340,28 @@ @Override public void onCancel() { - if (!mInputProtector.shouldInputBeProcessed()) return; + if (!mInputProtector.shouldInputBeProcessed() + && mTransactionMode == SPCTransactionMode.NONE) { + return; + } hide(); mResponseCallback.onResult(SpcResponseStatus.CANCEL); } private void onVerifyAnotherWay() { - if (!mInputProtector.shouldInputBeProcessed()) return; + if (!mInputProtector.shouldInputBeProcessed() + && mTransactionMode == SPCTransactionMode.NONE) { + return; + } hide(); mResponseCallback.onResult(SpcResponseStatus.ANOTHER_WAY); } private void onOptOut() { - if (!mInputProtector.shouldInputBeProcessed()) return; + if (!mInputProtector.shouldInputBeProcessed() + && mTransactionMode == SPCTransactionMode.NONE) { + return; + } hide(); mResponseCallback.onResult(SpcResponseStatus.OPT_OUT); }
diff --git a/components/payments/content/android/spc/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationControllerTest.java b/components/payments/content/android/spc/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationControllerTest.java index 8b5b865..1eb554b2 100644 --- a/components/payments/content/android/spc/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationControllerTest.java +++ b/components/payments/content/android/spc/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationControllerTest.java
@@ -46,6 +46,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; import org.chromium.components.payments.PaymentApp.PaymentEntityLogo; +import org.chromium.components.payments.SPCTransactionMode; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationController.SpcResponseStatus; import org.chromium.components.payments.secure_payment_confirmation.SecurePaymentConfirmationProperties.ItemProperties; import org.chromium.components.payments.ui.CurrencyFormatter; @@ -478,7 +479,73 @@ verifyNoInteractions(mBottomSheetController); } + @Test + public void testTransactionMode_autoAccept() { + createController( + /* showOptOut= */ false, /* informOnly= */ false, SPCTransactionMode.AUTOACCEPT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and accept the prompt. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.ACCEPT)); + } + + @Test + public void testTransactionMode_autoAccept_withInformOnly() { + createController( + /* showOptOut= */ false, /* informOnly= */ true, SPCTransactionMode.AUTOACCEPT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and accept the prompt. For the + // inform prompt, this is equivalent to verify another way. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.ANOTHER_WAY)); + } + + @Test + public void testTransactionMode_autoReject() { + createController( + /* showOptOut= */ false, /* informOnly= */ false, SPCTransactionMode.AUTOREJECT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and reject the prompt. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.CANCEL)); + } + + @Test + public void testTransactionMode_autoReject_withInformOnly() { + createController( + /* showOptOut= */ false, /* informOnly= */ true, SPCTransactionMode.AUTOREJECT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and reject the prompt. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.CANCEL)); + } + + @Test + public void testTransactionMode_autoOptOut() { + createController( + /* showOptOut= */ true, /* informOnly= */ false, SPCTransactionMode.AUTOOPTOUT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and opt out of the prompt. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.OPT_OUT)); + } + + @Test + public void testTransactionMode_autoOptOut_withInformOnly() { + createController( + /* showOptOut= */ true, /* informOnly= */ true, SPCTransactionMode.AUTOOPTOUT); + assertTrue(mController.show()); + + // The automation should run immediately when show is called, and opt out of the prompt. + verify(mResponseCallback).onResult(eq(SpcResponseStatus.OPT_OUT)); + } + private void createController(boolean showOptOut, boolean informOnly) { + createController(showOptOut, informOnly, SPCTransactionMode.NONE); + } + + private void createController( + boolean showOptOut, boolean informOnly, @SPCTransactionMode int transactionMode) { mController = new SecurePaymentConfirmationController( mWindow, @@ -492,7 +559,8 @@ mRelyingPartyId, showOptOut, informOnly, - mResponseCallback); + mResponseCallback, + transactionMode); InputProtector inputProtector = new InputProtector(mClock); inputProtector.markShowTime(); mController.setInputProtectorForTesting(inputProtector);
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index a21dc91..430900ae 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -21,6 +21,7 @@ #include "components/payments/content/payment_request_converter.h" #include "components/payments/content/payment_request_web_contents_manager.h" #include "components/payments/content/secure_payment_confirmation_no_creds.h" +#include "components/payments/content/secure_payment_confirmation_transaction_mode.h" #include "components/payments/core/error_message_util.h" #include "components/payments/core/error_strings.h" #include "components/payments/core/features.h"
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h index e30131f..ab9c37f 100644 --- a/components/payments/content/payment_request.h +++ b/components/payments/content/payment_request.h
@@ -32,13 +32,7 @@ namespace payments { class ContentPaymentRequestDelegate; - -enum class SPCTransactionMode { - NONE, - AUTOACCEPT, - AUTOREJECT, - AUTOOPTOUT, -}; +enum class SPCTransactionMode; // This class manages the interaction between the renderer (through the // PaymentRequestClient and Mojo stub implementation) and the desktop Payment UI
diff --git a/components/payments/content/payment_request_web_contents_manager.h b/components/payments/content/payment_request_web_contents_manager.h index 3733a69..a959f33 100644 --- a/components/payments/content/payment_request_web_contents_manager.h +++ b/components/payments/content/payment_request_web_contents_manager.h
@@ -5,7 +5,8 @@ #ifndef COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_ #define COMPONENTS_PAYMENTS_CONTENT_PAYMENT_REQUEST_WEB_CONTENTS_MANAGER_H_ -#include "components/payments/content/payment_request.h" +#include "components/payments/content/secure_payment_confirmation_transaction_mode.h" +#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" namespace content {
diff --git a/components/payments/content/payment_request_web_contents_manager_unittest.cc b/components/payments/content/payment_request_web_contents_manager_unittest.cc index 779b2d6..b8acb53 100644 --- a/components/payments/content/payment_request_web_contents_manager_unittest.cc +++ b/components/payments/content/payment_request_web_contents_manager_unittest.cc
@@ -6,6 +6,7 @@ #include "base/memory/raw_ptr.h" #include "components/autofill/core/browser/data_manager/test_personal_data_manager.h" +#include "components/payments/content/payment_request.h" #include "components/payments/content/test_content_payment_request_delegate.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_task_environment.h"
diff --git a/components/payments/content/secure_payment_confirmation_controller.cc b/components/payments/content/secure_payment_confirmation_controller.cc index ffe28814..dc71e29 100644 --- a/components/payments/content/secure_payment_confirmation_controller.cc +++ b/components/payments/content/secure_payment_confirmation_controller.cc
@@ -15,6 +15,7 @@ #include "components/payments/content/content_payment_request_delegate.h" #include "components/payments/content/payment_request.h" #include "components/payments/content/secure_payment_confirmation_app.h" +#include "components/payments/content/secure_payment_confirmation_transaction_mode.h" #include "components/payments/core/currency_formatter.h" #include "components/payments/core/features.h" #include "components/payments/core/method_strings.h"
diff --git a/components/payments/content/secure_payment_confirmation_transaction_mode.h b/components/payments/content/secure_payment_confirmation_transaction_mode.h new file mode 100644 index 0000000..6fd8671 --- /dev/null +++ b/components/payments/content/secure_payment_confirmation_transaction_mode.h
@@ -0,0 +1,24 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PAYMENTS_CONTENT_SECURE_PAYMENT_CONFIRMATION_TRANSACTION_MODE_H_ +#define COMPONENTS_PAYMENTS_CONTENT_SECURE_PAYMENT_CONFIRMATION_TRANSACTION_MODE_H_ + +namespace payments { + +// Represents the WebDriver automation 'modes' that the SPC UX can be put into. +// See https://w3c.github.io/secure-payment-confirmation/#sctn-automation +// +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.payments +// GENERATED_JAVA_CLASS_NAME_OVERRIDE: SPCTransactionMode +enum class SPCTransactionMode { + NONE, + AUTOACCEPT, + AUTOREJECT, + AUTOOPTOUT, +}; + +} // namespace payments + +#endif // COMPONENTS_PAYMENTS_CONTENT_SECURE_PAYMENT_CONFIRMATION_TRANSACTION_MODE_H_
diff --git a/components/policy/resources/templates/policy_definitions/GenerativeAI/GeminiSettings.yaml b/components/policy/resources/templates/policy_definitions/GenerativeAI/GeminiSettings.yaml index 0d635f5..efc9f089 100644 --- a/components/policy/resources/templates/policy_definitions/GenerativeAI/GeminiSettings.yaml +++ b/components/policy/resources/templates/policy_definitions/GenerativeAI/GeminiSettings.yaml
@@ -38,4 +38,5 @@ supported_on: - chrome.win:137- - chrome.mac:137- +- ios:139- tags: []
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/SiteSearchSettings.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/SiteSearchSettings.yaml index 239f10a0ef..840ce684 100644 --- a/components/policy/resources/templates/policy_definitions/Miscellaneous/SiteSearchSettings.yaml +++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/SiteSearchSettings.yaml
@@ -12,7 +12,9 @@ Site search entries configured as featured are displayed in the address bar when the user types "@". Up to three entries can be selected as featured. - Users cannot edit or disable site search entries set by policy, but they can add new shortcuts for the same URL. In addition, users cannot create new site search entries with a shortcut previously created via this policy. + For a site search entry where <ph name="ALLOW_USER_OVERRIDE_SITE_SEARCH_SETTINGS_FIELD">allow_user_override</ph> is true, users have the ability to edit or disable that entry. However, featured engines (beginning with "@") can only be disabled. If a user modifies an entry that was initially created by this policy, it will no longer be managed by policy and will be treated like a user-created shortcut. When <ph name="ALLOW_USER_OVERRIDE_SITE_SEARCH_SETTINGS_FIELD">allow_user_override</ph> is false or unspecified for a site search entry, users cannot edit or disable that entry. The setting to allow user override is only supported on M139 and later; earlier versions will default to disabling user override. + + Users cannot create new site search entries with a shortcut previously created via this policy unless <ph name="ALLOW_USER_OVERRIDE_SITE_SEARCH_SETTINGS_FIELD">allow_user_override</ph> is set to true for the site search entry. In case of a conflict with a shortcut previously created by the user, the user setting takes precedence. However, users can still trigger the option created by the policy by typing "@" in the search bar. For example, if the user already defined "work" as a shortcut to URL1 and the policy defines "work" as a shortcut to URL2, then typing "work" in the search bar will trigger a search to URL1, but typing "@work" in the search bar will trigger a search to URL2. @@ -28,6 +30,10 @@ - name: YouTube shortcut: youtube url: https://www.youtube.com/results?search_query=%s +- name: Google Drive + shortcut: drive + url: https://drive.google.com/?q=%s + allow_user_override: true features: dynamic_refresh: true per_profile: true @@ -47,6 +53,8 @@ type: string url: type: string + allow_user_override: + type: boolean required: - shortcut - name
diff --git a/components/safe_browsing/android/BUILD.gn b/components/safe_browsing/android/BUILD.gn index 9550654..db59c34 100644 --- a/components/safe_browsing/android/BUILD.gn +++ b/components/safe_browsing/android/BUILD.gn
@@ -162,6 +162,22 @@ sources = [ "native_java_unittests/src/org/chromium/components/safe_browsing/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.java" ] } +source_set("unit_tests_mobile_test_support") { + testonly = true + sources = [ + "safe_browsing_api_handler_test_util.cc", + "safe_browsing_api_handler_test_util.h", + ] + deps = [ + ":native_j_unittests_jni_headers", + ":safe_browsing_api_handler", + ":safe_browsing_api_handler_util", + "//base", + "//testing/gtest", + "//url", + ] +} + source_set("unit_tests_mobile") { testonly = true sources = [ @@ -170,11 +186,11 @@ "safe_browsing_api_handler_util_unittest.cc", ] deps = [ - ":native_j_unittests_jni_headers", ":native_java_unittests_java", ":remote_database_manager", ":safe_browsing_api_handler", ":safe_browsing_api_handler_util", + ":unit_tests_mobile_test_support", "//base", "//components/resources:components_resources_grit", "//components/safe_browsing/android:realtimeallowlist_proto",
diff --git a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/SafetyNetApiHandler.java b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/SafetyNetApiHandler.java index 5fec858..c51bd81 100644 --- a/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/SafetyNetApiHandler.java +++ b/components/safe_browsing/android/java/src/org/chromium/components/safe_browsing/SafetyNetApiHandler.java
@@ -53,12 +53,13 @@ int initialize(Observer observer); /** - * Start a check to determine if a uri is in an allowlist. If true, password protection service - * will consider the uri to be safe. Requires initialized state {@code INITIALIZED} or {@code + * Start a check to determine if a uri is in an allowlist. If true, Safe Browsing will consider + * the uri to be safe. Requires initialized state {@code INITIALIZED} or {@code * INITIALIZED_FIRST_PARTY}. * - * @param uri The uri from a password protection event(user focuses on password form or user - * reuses their password) + * @param uri The uri from a safe browsing relevant event (for password protection: user focuses + * on password form or user reuses their password; for download protection: a downloaded + * file of appropriate filetype). * @param threatType determines the type of the allowlist that the uri will be matched to. * @return true if the uri is found in the corresponding allowlist. Otherwise, false. */
diff --git a/components/safe_browsing/android/native_java_unittests/src/org/chromium/components/safe_browsing/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.java b/components/safe_browsing/android/native_java_unittests/src/org/chromium/components/safe_browsing/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.java index a192199..be1be4a 100644 --- a/components/safe_browsing/android/native_java_unittests/src/org/chromium/components/safe_browsing/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.java +++ b/components/safe_browsing/android/native_java_unittests/src/org/chromium/components/safe_browsing/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.java
@@ -24,7 +24,8 @@ */ public static class MockSafetyNetApiHandler implements SafetyNetApiHandler { private Observer mObserver; - // See safe_browsing_handler_util.h --> JavaThreatTypes + // See safe_browsing_api_handler_util.h --> SafetyNetJavaThreatType + private static final int THREAT_TYPE_CSD_DOWNLOAD_ALLOWLIST = 9; private static final int THREAT_TYPE_CSD_ALLOWLIST = 16; // The result that will be returned in {@link #isVerifyAppsEnabled(long)} or {@link // #enableVerifyApps(long)}. @@ -32,6 +33,7 @@ // Maps to store preset values, keyed by uri. private static final Map<String, Boolean> sCsdAllowlistMap = new HashMap<>(); + private static final Map<String, Boolean> sCsdDownloadAllowlistMap = new HashMap<>(); // The initialization state of the API handler. The default value of -1 signifies // uninitialized. @@ -54,8 +56,14 @@ @Override public boolean startAllowlistLookup(final String uri, int threatType) { - Assert.assertTrue(threatType == THREAT_TYPE_CSD_ALLOWLIST); - return Boolean.TRUE.equals(sCsdAllowlistMap.get(uri)); + if (threatType == THREAT_TYPE_CSD_ALLOWLIST) { + return Boolean.TRUE.equals(sCsdAllowlistMap.get(uri)); + } + if (threatType == THREAT_TYPE_CSD_DOWNLOAD_ALLOWLIST) { + return Boolean.TRUE.equals(sCsdDownloadAllowlistMap.get(uri)); + } + assert false : "Unsupported threatType"; + return false; } @Override @@ -81,6 +89,7 @@ public static void tearDown() { sCsdAllowlistMap.clear(); + sCsdDownloadAllowlistMap.clear(); sSafetyNetApiInitializationState = -1; sGetSafetyNetIdCount = 0; } @@ -89,6 +98,10 @@ sCsdAllowlistMap.put(uri, match); } + public static void setCsdDownloadAllowlistMatch(String uri, boolean match) { + sCsdDownloadAllowlistMap.put(uri, match); + } + public static void setVerifyAppsResult(int result) { sVerifyAppsResult = result; } @@ -242,6 +255,11 @@ } @CalledByNative + static void setCsdDownloadAllowlistMatch(String uri, boolean match) { + MockSafetyNetApiHandler.setCsdDownloadAllowlistMatch(uri, match); + } + + @CalledByNative static void setSafeBrowsingApiHandlerResponse( String uri, int[] expectedThreatTypes,
diff --git a/components/safe_browsing/android/remote_database_manager.cc b/components/safe_browsing/android/remote_database_manager.cc index 09992f9..45bf1878 100644 --- a/components/safe_browsing/android/remote_database_manager.cc +++ b/components/safe_browsing/android/remote_database_manager.cc
@@ -245,11 +245,17 @@ const GURL& url, base::OnceCallback<void(bool)> callback) { DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); - // The allowlist check is not yet implemented. - // TODO(crbug.com/397407934): Implement checking UrlCsdDownloadAllowlist. + bool is_match = false; + // Note: non-supported URL schemes by default do NOT match the allowlist. + if (CanCheckUrl(url)) { + // Check a local copy of UrlCsdDownloadAllowlist. + // TODO(crbug.com/418842288): Improve this list. + is_match = SafeBrowsingApiHandlerBridge::GetInstance() + .StartCSDDownloadAllowlistCheck(url); + } ui_task_runner()->PostTask(FROM_HERE, base::BindOnce(std::move(callback), - /*is_allowlisted=*/false)); + /*is_allowlisted=*/is_match)); } safe_browsing::ThreatSource
diff --git a/components/safe_browsing/android/remote_database_manager_unittest.cc b/components/safe_browsing/android/remote_database_manager_unittest.cc index 4f065a94..ec5efca 100644 --- a/components/safe_browsing/android/remote_database_manager_unittest.cc +++ b/components/safe_browsing/android/remote_database_manager_unittest.cc
@@ -12,8 +12,10 @@ #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "base/time/time.h" #include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h" +#include "components/safe_browsing/android/safe_browsing_api_handler_test_util.h" #include "components/safe_browsing/core/browser/db/database_manager.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/browser/db/v4_test_util.h" @@ -88,13 +90,16 @@ } // namespace -class RemoteDatabaseManagerTest : public testing::Test { +class RemoteDatabaseManagerTest + : public testing::Test, + public safe_browsing::test::WithMockSafeBrowsingApiHandler { protected: using enum SBThreatType; RemoteDatabaseManagerTest() = default; void SetUp() override { + safe_browsing::test::WithMockSafeBrowsingApiHandler::SetUp(); test_shared_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &test_url_loader_factory_); @@ -110,6 +115,7 @@ void TearDown() override { db_->StopOnUIThread(/*shutdown=*/false); db_ = nullptr; + safe_browsing::test::WithMockSafeBrowsingApiHandler::TearDown(); } content::BrowserTaskEnvironment task_environment_; @@ -173,4 +179,40 @@ db_->GetBrowseUrlThreatSource(CheckBrowseUrlType::kHashRealTime)); } +TEST_F(RemoteDatabaseManagerTest, MatchDownloadAllowlistUrl) { + GURL allowlisted_url{"https://www.example.test"}; + AddLocalAllowlistEntry(allowlisted_url, /*is_download_allowlist=*/true, + /*is_match=*/true); + + // Allowlisted URL should match. + { + base::test::TestFuture<bool> result_future; + db_->MatchDownloadAllowlistUrl(allowlisted_url, + result_future.GetCallback()); + EXPECT_TRUE(result_future.Get()); + } + + // Not on the allowlist. + { + GURL url{"https://www.notexample.test"}; + base::test::TestFuture<bool> result_future; + db_->MatchDownloadAllowlistUrl(url, result_future.GetCallback()); + EXPECT_FALSE(result_future.Get()); + } + + // Not checked because of URL scheme. + { + GURL url{"data:,Hello%2C%20World%21"}; + base::test::TestFuture<bool> result_future; + db_->MatchDownloadAllowlistUrl(url, result_future.GetCallback()); + EXPECT_FALSE(result_future.Get()); + } + { + GURL url{"file:///usr/home/foo"}; + base::test::TestFuture<bool> result_future; + db_->MatchDownloadAllowlistUrl(url, result_future.GetCallback()); + EXPECT_FALSE(result_future.Get()); + } +} + } // namespace safe_browsing
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc b/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc index e6012ba..9463313 100644 --- a/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc +++ b/components/safe_browsing/android/safe_browsing_api_handler_bridge.cc
@@ -420,7 +420,7 @@ return *pending_get_safety_net_id_callbacks; } -bool StartAllowlistCheck(const GURL& url, const SBThreatType& sb_threat_type) { +bool StartAllowlistCheck(const GURL& url, SafetyNetJavaThreatType threat_type) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); JNIEnv* env = AttachCurrentThread(); if (!Java_SafeBrowsingApiBridge_ensureSafetyNetApiInitialized(env)) { @@ -428,8 +428,7 @@ } ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec()); - int j_threat_type = - static_cast<int>(SBThreatTypeToSafetyNetJavaThreatType(sb_threat_type)); + int j_threat_type = static_cast<int>(threat_type); return Java_SafeBrowsingApiBridge_startAllowlistLookup(env, j_url, j_threat_type); } @@ -663,10 +662,15 @@ } bool SafeBrowsingApiHandlerBridge::StartCSDAllowlistCheck(const GURL& url) { - if (interceptor_for_testing_) - return false; return StartAllowlistCheck( - url, safe_browsing::SBThreatType::SB_THREAT_TYPE_CSD_ALLOWLIST); + url, SBThreatTypeToSafetyNetJavaThreatType( + safe_browsing::SBThreatType::SB_THREAT_TYPE_CSD_ALLOWLIST)); +} + +bool SafeBrowsingApiHandlerBridge::StartCSDDownloadAllowlistCheck( + const GURL& url) { + return StartAllowlistCheck(url, + SafetyNetJavaThreatType::CSD_DOWNLOAD_ALLOWLIST); } void SafeBrowsingApiHandlerBridge::StartIsVerifyAppsEnabled(
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_bridge.h b/components/safe_browsing/android/safe_browsing_api_handler_bridge.h index dc7b225..9d6131c 100644 --- a/components/safe_browsing/android/safe_browsing_api_handler_bridge.h +++ b/components/safe_browsing/android/safe_browsing_api_handler_bridge.h
@@ -60,7 +60,9 @@ const GURL& url, const SBThreatTypeSet& threat_types); + // Check whether `url` matches a local allowlist. bool StartCSDAllowlistCheck(const GURL& url); + bool StartCSDDownloadAllowlistCheck(const GURL& url); // Query whether app verification is enabled. Will run `callback` with // the result of the query.
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_bridge_unittest.cc b/components/safe_browsing/android/safe_browsing_api_handler_bridge_unittest.cc index b44c4ca..72f9bee 100644 --- a/components/safe_browsing/android/safe_browsing_api_handler_bridge_unittest.cc +++ b/components/safe_browsing/android/safe_browsing_api_handler_bridge_unittest.cc
@@ -4,15 +4,12 @@ #include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h" -#include "base/android/jni_android.h" -#include "base/android/jni_array.h" -#include "base/android/jni_string.h" -#include "base/containers/heap_array.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_future.h" #include "base/types/fixed_array.h" +#include "components/safe_browsing/android/safe_browsing_api_handler_test_util.h" #include "components/safe_browsing/android/safe_browsing_api_handler_util.h" #include "components/safe_browsing/core/browser/db/util.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" @@ -23,22 +20,12 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -// Must come after all headers that specialize FromJniType() / ToJniType(). -#include "components/safe_browsing/android/native_j_unittests_jni_headers/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_jni.h" - -using base::android::ConvertUTF8ToJavaString; -using base::android::ScopedJavaLocalRef; -using base::android::ToJavaIntArray; - -using ::testing::NotNull; - namespace safe_browsing { namespace { -// This value should be aligned with DEFAULT_CHECK_DELTA_MICROSECONDS in -// SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.MockSafeBrowsingApiHandler. -constexpr int kExpectedSafeBrowsingCheckDeltaMicroseconds = 15; +using SafetyNetApiInitializationState = + safe_browsing::test::SafetyNetApiInitializationState; std::vector<SafeBrowsingJavaThreatType> GetAllSafeBrowsingThreatTypes() { return {SafeBrowsingJavaThreatType::SOCIAL_ENGINEERING, @@ -54,16 +41,11 @@ SBThreatType::SB_THREAT_TYPE_BILLING}); } -// Test-only mirror of SafetyNetApiHandler.SafetyNetApiState in Java. -enum class SafetyNetApiInitializationState { - kNotAvailable = 0, - kInitialized = 1, - kInitializedFirstParty = 2, -}; - } // namespace -class SafeBrowsingApiHandlerBridgeTest : public testing::Test { +class SafeBrowsingApiHandlerBridgeTest + : public testing::Test, + public safe_browsing::test::WithMockSafeBrowsingApiHandler { public: SafeBrowsingApiHandlerBridgeTest() { base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( @@ -72,115 +54,16 @@ } void SetUp() override { - env_ = base::android::AttachCurrentThread(); - ASSERT_THAT(env_, NotNull()); - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setUp(env_); + safe_browsing::test::WithMockSafeBrowsingApiHandler::SetUp(); } void TearDown() override { - SafeBrowsingApiHandlerBridge::GetInstance() - .ResetSafeBrowsingApiAvailableForTesting(); - SafeBrowsingApiHandlerBridge::GetInstance().ResetSafetyNetIdForTesting(); - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_tearDown(env_); + safe_browsing::test::WithMockSafeBrowsingApiHandler::TearDown(); } protected: using enum SBThreatType; - void AddSafeBrowsingResponse( - const GURL& url, - const SafeBrowsingApiLookupResult& returned_lookup_result, - const SafeBrowsingJavaThreatType& returned_threat_type, - const std::vector<SafeBrowsingJavaThreatAttribute>& - returned_threat_attributes, - const SafeBrowsingJavaResponseStatus& returned_response_status, - const std::vector<SafeBrowsingJavaThreatType>& expected_threat_types, - const SafeBrowsingJavaProtocol& expected_protocol) { - ScopedJavaLocalRef<jstring> j_url = - ConvertUTF8ToJavaString(env_, url.spec()); - auto int_threat_types = - base::HeapArray<int>::WithSize(expected_threat_types.size()); - auto itr = int_threat_types.begin(); - for (auto expected_threat_type : expected_threat_types) { - *itr++ = static_cast<int>(expected_threat_type); - } - auto int_threat_attributes = - base::HeapArray<int>::WithSize(returned_threat_attributes.size()); - itr = int_threat_attributes.begin(); - for (auto returned_threat_attribute : returned_threat_attributes) { - *itr++ = static_cast<int>(returned_threat_attribute); - } - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafeBrowsingApiHandlerResponse( - env_, j_url, ToJavaIntArray(env_, int_threat_types), - static_cast<int>(expected_protocol), - static_cast<int>(returned_lookup_result), - static_cast<int>(returned_threat_type), - ToJavaIntArray(env_, int_threat_attributes), - static_cast<int>(returned_response_status)); - } - - void SetVerifyAppsResult(VerifyAppsEnabledResult result) { - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setVerifyAppsResult( - env_, static_cast<int>(result)); - } - - void SetSafetyNetApiInitializationState( - SafetyNetApiInitializationState state) { - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafetyNetApiInitializationState( - env_, static_cast<int>(state)); - } - - void SetSafetyNetIdResultEmpty() { - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafetyNetIdResultEmpty( - env_); - } - - void RunHashDatabaseUrlCheck( - const GURL& url, - const SBThreatTypeSet& threat_types, - SBThreatType expected_threat_type, - SubresourceFilterMatch expected_subresource_filter_match) { - base::RunLoop run_loop; - auto callback = - SafeBrowsingApiHandlerBridge::ResponseCallback(base::BindOnce( - [](base::RunLoop* run_loop, SBThreatType expected_threat_type, - SubresourceFilterMatch expected_subresource_filter_match, - SBThreatType returned_threat_type, - const ThreatMetadata& returned_metadata) { - EXPECT_EQ(returned_threat_type, expected_threat_type); - EXPECT_EQ(returned_metadata.subresource_filter_match, - expected_subresource_filter_match); - run_loop->Quit(); - }, - &run_loop, expected_threat_type, - expected_subresource_filter_match)); - SafeBrowsingApiHandlerBridge::GetInstance().StartHashDatabaseUrlCheck( - std::move(callback), url, threat_types); - run_loop.Run(); - } - - void RunHashRealTimeUrlCheck(const GURL& url, - const SBThreatTypeSet& threat_types, - SBThreatType expected_threat_type) { - base::RunLoop run_loop; - auto callback = - SafeBrowsingApiHandlerBridge::ResponseCallback(base::BindOnce( - [](base::RunLoop* run_loop, SBThreatType expected_threat_type, - SBThreatType returned_threat_type, - const ThreatMetadata& returned_metadata) { - EXPECT_EQ(returned_threat_type, expected_threat_type); - run_loop->Quit(); - }, - &run_loop, expected_threat_type)); - SafeBrowsingApiHandlerBridge::GetInstance().StartHashRealTimeUrlCheck( - std::move(callback), url, threat_types); - run_loop.Run(); - EXPECT_EQ( - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_getSafeBrowsingApiUrlCheckTimeObserverResult( - env_), - kExpectedSafeBrowsingCheckDeltaMicroseconds); - } - void CheckSafeBrowsingApiHistogramValues( const std::string& suffix, bool expected_is_available, @@ -304,7 +187,6 @@ } } - raw_ptr<JNIEnv> env_; content::BrowserTaskEnvironment task_environment_; base::HistogramTester histogram_tester_; }; @@ -488,17 +370,39 @@ /*expected_subresource_filter_match=*/{}); } -TEST_F(SafeBrowsingApiHandlerBridgeTest, CsdAllowlistCheck) { - GURL url("https://example.com"); - ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env_, url.spec()); - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setCsdAllowlistMatch( - env_, j_url, true); +TEST_F(SafeBrowsingApiHandlerBridgeTest, CheckLocalAllowlists) { + SetSafetyNetApiInitializationState( + SafetyNetApiInitializationState::kInitialized); + + GURL url1("https://example.com"); + GURL url2("https://download.test"); + GURL url3("https://bothlists.test"); + AddLocalAllowlistEntry(url1, /*is_download_allowlist=*/false, + /*is_match=*/true); + AddLocalAllowlistEntry(url2, /*is_download_allowlist=*/false, + /*is_match=*/false); + AddLocalAllowlistEntry(url3, /*is_download_allowlist=*/false, + /*is_match=*/true); + AddLocalAllowlistEntry(url1, /*is_download_allowlist=*/true, + /*is_match=*/false); + AddLocalAllowlistEntry(url2, /*is_download_allowlist=*/true, + /*is_match=*/true); + AddLocalAllowlistEntry(url3, /*is_download_allowlist=*/true, + /*is_match=*/true); + EXPECT_TRUE( - SafeBrowsingApiHandlerBridge::GetInstance().StartCSDAllowlistCheck(url)); - Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setCsdAllowlistMatch( - env_, j_url, false); + SafeBrowsingApiHandlerBridge::GetInstance().StartCSDAllowlistCheck(url1)); EXPECT_FALSE( - SafeBrowsingApiHandlerBridge::GetInstance().StartCSDAllowlistCheck(url)); + SafeBrowsingApiHandlerBridge::GetInstance().StartCSDAllowlistCheck(url2)); + EXPECT_TRUE( + SafeBrowsingApiHandlerBridge::GetInstance().StartCSDAllowlistCheck(url3)); + + EXPECT_FALSE(SafeBrowsingApiHandlerBridge::GetInstance() + .StartCSDDownloadAllowlistCheck(url1)); + EXPECT_TRUE(SafeBrowsingApiHandlerBridge::GetInstance() + .StartCSDDownloadAllowlistCheck(url2)); + EXPECT_TRUE(SafeBrowsingApiHandlerBridge::GetInstance() + .StartCSDDownloadAllowlistCheck(url3)); } TEST_F(SafeBrowsingApiHandlerBridgeTest, HashRealTimeUrlCheck_Safe) {
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_test_util.cc b/components/safe_browsing/android/safe_browsing_api_handler_test_util.cc new file mode 100644 index 0000000..174bbf7 --- /dev/null +++ b/components/safe_browsing/android/safe_browsing_api_handler_test_util.cc
@@ -0,0 +1,143 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/safe_browsing/android/safe_browsing_api_handler_test_util.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/containers/heap_array.h" +#include "base/run_loop.h" +#include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +// Must come after all headers that specialize FromJniType() / ToJniType(). +#include "components/safe_browsing/android/native_j_unittests_jni_headers/SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_jni.h" + +namespace safe_browsing::test { + +void WithMockSafeBrowsingApiHandler::SetUp() { + env_ = base::android::AttachCurrentThread(); + ASSERT_TRUE(env_); + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setUp(env_); +} + +void WithMockSafeBrowsingApiHandler::TearDown() { + SafeBrowsingApiHandlerBridge::GetInstance() + .ResetSafeBrowsingApiAvailableForTesting(); + SafeBrowsingApiHandlerBridge::GetInstance().ResetSafetyNetIdForTesting(); + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_tearDown(env_); +} + +void WithMockSafeBrowsingApiHandler::SetSafetyNetApiInitializationState( + SafetyNetApiInitializationState state) { + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafetyNetApiInitializationState( + env_, static_cast<int>(state)); +} + +void WithMockSafeBrowsingApiHandler::SetVerifyAppsResult( + VerifyAppsEnabledResult result) { + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setVerifyAppsResult( + env_, static_cast<int>(result)); +} + +void WithMockSafeBrowsingApiHandler::SetSafetyNetIdResultEmpty() { + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafetyNetIdResultEmpty( + env_); +} + +void WithMockSafeBrowsingApiHandler::AddLocalAllowlistEntry( + const GURL& url, + bool is_download_allowlist, + bool is_match) { + base::android::ScopedJavaLocalRef<jstring> j_url = + base::android::ConvertUTF8ToJavaString(env_, url.spec()); + + if (is_download_allowlist) { + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setCsdDownloadAllowlistMatch( + env_, j_url, is_match); + } else { + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setCsdAllowlistMatch( + env_, j_url, is_match); + } +} + +void WithMockSafeBrowsingApiHandler::AddSafeBrowsingResponse( + const GURL& url, + const SafeBrowsingApiLookupResult& returned_lookup_result, + const SafeBrowsingJavaThreatType& returned_threat_type, + const std::vector<SafeBrowsingJavaThreatAttribute>& + returned_threat_attributes, + const SafeBrowsingJavaResponseStatus& returned_response_status, + const std::vector<SafeBrowsingJavaThreatType>& expected_threat_types, + const SafeBrowsingJavaProtocol& expected_protocol) { + base::android::ScopedJavaLocalRef<jstring> j_url = + base::android::ConvertUTF8ToJavaString(env_, url.spec()); + auto int_threat_types = + base::HeapArray<int>::WithSize(expected_threat_types.size()); + auto itr = int_threat_types.begin(); + for (auto expected_threat_type : expected_threat_types) { + *itr++ = static_cast<int>(expected_threat_type); + } + auto int_threat_attributes = + base::HeapArray<int>::WithSize(returned_threat_attributes.size()); + itr = int_threat_attributes.begin(); + for (auto returned_threat_attribute : returned_threat_attributes) { + *itr++ = static_cast<int>(returned_threat_attribute); + } + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_setSafeBrowsingApiHandlerResponse( + env_, j_url, base::android::ToJavaIntArray(env_, int_threat_types), + static_cast<int>(expected_protocol), + static_cast<int>(returned_lookup_result), + static_cast<int>(returned_threat_type), + base::android::ToJavaIntArray(env_, int_threat_attributes), + static_cast<int>(returned_response_status)); +} + +void WithMockSafeBrowsingApiHandler::RunHashDatabaseUrlCheck( + const GURL& url, + const SBThreatTypeSet& threat_types, + SBThreatType expected_threat_type, + SubresourceFilterMatch expected_subresource_filter_match) { + base::RunLoop run_loop; + auto callback = SafeBrowsingApiHandlerBridge::ResponseCallback(base::BindOnce( + [](base::RunLoop* run_loop, SBThreatType expected_threat_type, + SubresourceFilterMatch expected_subresource_filter_match, + SBThreatType returned_threat_type, + const ThreatMetadata& returned_metadata) { + EXPECT_EQ(returned_threat_type, expected_threat_type); + EXPECT_EQ(returned_metadata.subresource_filter_match, + expected_subresource_filter_match); + run_loop->Quit(); + }, + &run_loop, expected_threat_type, expected_subresource_filter_match)); + SafeBrowsingApiHandlerBridge::GetInstance().StartHashDatabaseUrlCheck( + std::move(callback), url, threat_types); + run_loop.Run(); +} + +void WithMockSafeBrowsingApiHandler::RunHashRealTimeUrlCheck( + const GURL& url, + const SBThreatTypeSet& threat_types, + SBThreatType expected_threat_type) { + base::RunLoop run_loop; + auto callback = SafeBrowsingApiHandlerBridge::ResponseCallback(base::BindOnce( + [](base::RunLoop* run_loop, SBThreatType expected_threat_type, + SBThreatType returned_threat_type, + const ThreatMetadata& returned_metadata) { + EXPECT_EQ(returned_threat_type, expected_threat_type); + run_loop->Quit(); + }, + &run_loop, expected_threat_type)); + SafeBrowsingApiHandlerBridge::GetInstance().StartHashRealTimeUrlCheck( + std::move(callback), url, threat_types); + run_loop.Run(); + EXPECT_EQ( + Java_SafeBrowsingApiHandlerBridgeNativeUnitTestHelper_getSafeBrowsingApiUrlCheckTimeObserverResult( + env_), + kExpectedSafeBrowsingCheckDeltaMicroseconds); +} + +} // namespace safe_browsing::test
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_test_util.h b/components/safe_browsing/android/safe_browsing_api_handler_test_util.h new file mode 100644 index 0000000..10d41d4 --- /dev/null +++ b/components/safe_browsing/android/safe_browsing_api_handler_test_util.h
@@ -0,0 +1,78 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_TEST_UTIL_H_ +#define COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_TEST_UTIL_H_ + +#include "components/safe_browsing/android/safe_browsing_api_handler_util.h" + +class GURL; + +namespace safe_browsing::test { + +// Test-only mirror of SafetyNetApiHandler.SafetyNetApiState in Java. +enum class SafetyNetApiInitializationState { + kNotAvailable = 0, + kInitialized = 1, + kInitializedFirstParty = 2, +}; + +// Mixin for unittests that need to mock various functionality of +// SafeBrowsingApiHandlerBridge, SafeBrowsingApiHandler, and +// SafetyNetApiHandler. Test fixtures should inherit from this class to add the +// mock behavior. +class WithMockSafeBrowsingApiHandler { + public: + // This value should be aligned with DEFAULT_CHECK_DELTA_MICROSECONDS in + // SafeBrowsingApiHandlerBridgeNativeUnitTestHelper.MockSafeBrowsingApiHandler + static constexpr int kExpectedSafeBrowsingCheckDeltaMicroseconds = 15; + + // Call these in SetUp/TearDown for the test fixture. + void SetUp(); + void TearDown(); + + // Fake the initialization state for SafetyNetApiHandler. + void SetSafetyNetApiInitializationState( + SafetyNetApiInitializationState state); + + // Set a fake result for VerifyAppsEnabled. + void SetVerifyAppsResult(VerifyAppsEnabledResult result); + + // Make the SafetyNetId show up as empty string. + void SetSafetyNetIdResultEmpty(); + + // Add a fake entry to one of the local allowlists. Note that the fake + // allowlists do not check for domain and path match; they only check that the + // URL spec is identical. + void AddLocalAllowlistEntry(const GURL& url, + bool is_download_allowlist, + bool is_match); + + void AddSafeBrowsingResponse( + const GURL& url, + const SafeBrowsingApiLookupResult& returned_lookup_result, + const SafeBrowsingJavaThreatType& returned_threat_type, + const std::vector<SafeBrowsingJavaThreatAttribute>& + returned_threat_attributes, + const SafeBrowsingJavaResponseStatus& returned_response_status, + const std::vector<SafeBrowsingJavaThreatType>& expected_threat_types, + const SafeBrowsingJavaProtocol& expected_protocol); + + void RunHashDatabaseUrlCheck( + const GURL& url, + const SBThreatTypeSet& threat_types, + SBThreatType expected_threat_type, + SubresourceFilterMatch expected_subresource_filter_match); + + void RunHashRealTimeUrlCheck(const GURL& url, + const SBThreatTypeSet& threat_types, + SBThreatType expected_threat_type); + + protected: + raw_ptr<JNIEnv> env_; +}; + +} // namespace safe_browsing::test + +#endif // COMPONENTS_SAFE_BROWSING_ANDROID_SAFE_BROWSING_API_HANDLER_TEST_UTIL_H_
diff --git a/components/safe_browsing/android/safe_browsing_api_handler_util.h b/components/safe_browsing/android/safe_browsing_api_handler_util.h index bd1ff3f..ca4566d1 100644 --- a/components/safe_browsing/android/safe_browsing_api_handler_util.h +++ b/components/safe_browsing/android/safe_browsing_api_handler_util.h
@@ -14,9 +14,12 @@ namespace safe_browsing { // Threat types as per the Java code. -// This must match those in SafeBrowsingThreat.java in GMS's SafetyNet API. +// Threat type values must be consistent with values in SafeBrowsingThreat.java +// in GMS's SafetyNet API. enum class SafetyNetJavaThreatType { - // Magic numbers for allowlists. Not actually used by GMSCore. + // Below listed entries are magic numbers for allowlists. These are not + // actually threat types used by GMSCore. + CSD_DOWNLOAD_ALLOWLIST = 9, CSD_ALLOWLIST = 16, MAX_VALUE };
diff --git a/components/search_engines/enterprise/site_search_policy_handler_unittest.cc b/components/search_engines/enterprise/site_search_policy_handler_unittest.cc index 9ce71b6..ede2ffcc 100644 --- a/components/search_engines/enterprise/site_search_policy_handler_unittest.cc +++ b/components/search_engines/enterprise/site_search_policy_handler_unittest.cc
@@ -449,7 +449,7 @@ base::Value(std::move(policy_value)), nullptr); ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors)); - EXPECT_TRUE(errors.HasError(key::kSiteSearchSettings)); + ASSERT_FALSE(errors.HasError(key::kSiteSearchSettings)); handler.ApplyPolicySettings(policies, &prefs); base::Value* providers = nullptr; @@ -491,10 +491,8 @@ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, base::Value(std::move(policy_value)), nullptr); - // TODO(crbug.com/417479042): Remove error expectation once policy YAML - // includes new `allow_user_override` field. ASSERT_TRUE(handler.CheckPolicySettings(policies, &errors)); - EXPECT_TRUE(errors.HasError(key::kSiteSearchSettings)); + ASSERT_FALSE(errors.HasError(key::kSiteSearchSettings)); handler.ApplyPolicySettings(policies, &prefs); base::Value* providers = nullptr;
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 2fd7fd34..4351a245 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -1785,25 +1785,6 @@ } } -std::u16string TemplateURLService::GetKeywordShortName( - const std::u16string& keyword, - bool* is_omnibox_api_extension_keyword, - bool* is_gemini_keyword) const { - const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); - - // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService - // to track changes to the model, this should become a DCHECK. - if (template_url) { - *is_gemini_keyword = - template_url->starter_pack_id() == TemplateURLStarterPackData::kGemini; - *is_omnibox_api_extension_keyword = - template_url->type() == TemplateURL::OMNIBOX_API_EXTENSION; - return template_url->AdjustedShortNameForLocaleDirection(); - } - *is_omnibox_api_extension_keyword = false; - return std::u16string(); -} - void TemplateURLService::OnHistoryURLVisited(const URLVisitedDetails& details) { if (!loaded_) { visits_to_add_.push_back(details);
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h index 5b572cc..9a9b233 100644 --- a/components/search_engines/template_url_service.h +++ b/components/search_engines/template_url_service.h
@@ -497,13 +497,6 @@ KeywordWebDataService::Handle h, std::unique_ptr<WDTypedResult> result) override; - // Returns the locale-direction-adjusted short name for the given keyword. - // Also sets the out param to indicate whether the keyword belongs to an - // Omnibox extension or the Gemini starter pack engine. - std::u16string GetKeywordShortName(const std::u16string& keyword, - bool* is_omnibox_api_extension_keyword, - bool* is_gemini_keyword) const; - // Called by the history service when a URL is visited. void OnHistoryURLVisited(const URLVisitedDetails& details);
diff --git a/components/services/storage/dom_storage/local_storage_impl.cc b/components/services/storage/dom_storage/local_storage_impl.cc index f34fedf2..cea2602e 100644 --- a/components/services/storage/dom_storage/local_storage_impl.cc +++ b/components/services/storage/dom_storage/local_storage_impl.cc
@@ -41,7 +41,6 @@ #include "components/services/storage/dom_storage/local_storage_database.pb.h" #include "components/services/storage/dom_storage/storage_area_impl.h" #include "components/services/storage/public/cpp/constants.h" -#include "components/services/storage/storage_service_impl.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "storage/common/database/database_identifier.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -336,11 +335,11 @@ }; LocalStorageImpl::LocalStorageImpl( - StorageServiceImpl& service, const base::FilePath& storage_root, scoped_refptr<base::SequencedTaskRunner> task_runner, + DestructLocalStorageCallback destruct_callback, mojo::PendingReceiver<mojom::LocalStorageControl> receiver) - : service_(service), + : destruct_callback_(std::move(destruct_callback)), directory_(storage_root.empty() ? storage_root : storage_root.Append(kLocalStoragePath)), database_task_runner_(base::ThreadPool::CreateSequencedTaskRunner( @@ -1095,8 +1094,7 @@ } void LocalStorageImpl::OnReceiverDisconnected() { - ShutDown(base::DoNothing()); - service_->RemoveLocalStorage(this); + std::move(destruct_callback_).Run(this); } } // namespace storage
diff --git a/components/services/storage/dom_storage/local_storage_impl.h b/components/services/storage/dom_storage/local_storage_impl.h index 4f86ae2..d5843aa 100644 --- a/components/services/storage/dom_storage/local_storage_impl.h +++ b/components/services/storage/dom_storage/local_storage_impl.h
@@ -46,15 +46,17 @@ class LocalStorageImpl : public base::trace_event::MemoryDumpProvider, public mojom::LocalStorageControl { public: + using DestructLocalStorageCallback = + base::OnceCallback<void(LocalStorageImpl*)>; // Constructs a Local Storage implementation which will create its root // "Local Storage" directory in |storage_root| if non-empty. |task_runner| // run tasks on the same sequence as the one which constructs this object. // |legacy_task_runner| must support blocking operations and its tasks must // be able to block shutdown. If valid, |receiver| will be bound to this // object to allow for remote control via the LocalStorageControl interface. - LocalStorageImpl(StorageServiceImpl& service, - const base::FilePath& storage_root, + LocalStorageImpl(const base::FilePath& storage_root, scoped_refptr<base::SequencedTaskRunner> task_runner, + DestructLocalStorageCallback destruct_callback, mojo::PendingReceiver<mojom::LocalStorageControl> receiver); ~LocalStorageImpl() override; @@ -158,8 +160,10 @@ std::vector<DomStorageDatabase::KeyValuePair> data); void OnReceiverDisconnected(); - // The StorageServiceImpl that owns this object. - const raw_ref<StorageServiceImpl> service_; + // Passed in by the StorageServiceImpl that owns this object. Used to signal + // that this LocalStorageImpl can be destructed when the Receiver is + // disconnected. + DestructLocalStorageCallback destruct_callback_; const base::FilePath directory_; enum ConnectionState {
diff --git a/components/services/storage/dom_storage/local_storage_impl_unittest.cc b/components/services/storage/dom_storage/local_storage_impl_unittest.cc index e912d92..4ef4fe46 100644 --- a/components/services/storage/dom_storage/local_storage_impl_unittest.cc +++ b/components/services/storage/dom_storage/local_storage_impl_unittest.cc
@@ -31,7 +31,6 @@ #include "components/services/storage/public/cpp/filesystem/filesystem_proxy.h" #include "components/services/storage/public/mojom/storage_service.mojom.h" #include "components/services/storage/public/mojom/storage_usage_info.mojom.h" -#include "components/services/storage/storage_service_impl.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/base/features.h" #include "testing/gtest/include/gtest/gtest.h" @@ -140,8 +139,8 @@ void InitializeStorage(const base::FilePath& path) { DCHECK(!storage_); storage_ = std::make_unique<LocalStorageImpl>( - storage_service_, path, - base::SingleThreadTaskRunner::GetCurrentDefault(), + path, base::SingleThreadTaskRunner::GetCurrentDefault(), + base::NullCallback(), /*receiver=*/mojo::NullReceiver()); } @@ -299,10 +298,6 @@ } base::test::TaskEnvironment task_environment_; - mojo::Remote<mojom::StorageService> remote_service_; - StorageServiceImpl storage_service_{ - remote_service_.BindNewPipeAndPassReceiver(), - /*io_task_runner=*/nullptr}; base::ScopedTempDir temp_path_; std::unique_ptr<LocalStorageImpl> storage_;
diff --git a/components/services/storage/dom_storage/session_storage_impl.cc b/components/services/storage/dom_storage/session_storage_impl.cc index ad3d6e6f..fcf42875 100644 --- a/components/services/storage/dom_storage/session_storage_impl.cc +++ b/components/services/storage/dom_storage/session_storage_impl.cc
@@ -26,7 +26,6 @@ #include "components/services/storage/dom_storage/async_dom_storage_database.h" #include "components/services/storage/dom_storage/dom_storage_database.h" #include "components/services/storage/dom_storage/session_storage_area_impl.h" -#include "components/services/storage/storage_service_impl.h" #include "mojo/public/cpp/bindings/callback_helpers.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "third_party/blink/public/common/storage_key/storage_key.h" @@ -95,14 +94,14 @@ } // namespace SessionStorageImpl::SessionStorageImpl( - StorageServiceImpl& service, const base::FilePath& partition_directory, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, scoped_refptr<base::SequencedTaskRunner> memory_dump_task_runner, BackingMode backing_mode, std::string database_name, + DestructSessionStorageCallback destruct_callback, mojo::PendingReceiver<mojom::SessionStorageControl> receiver) - : service_(service), + : destruct_callback_(std::move(destruct_callback)), backing_mode_(backing_mode), database_name_(std::move(database_name)), partition_directory_(partition_directory), @@ -1045,8 +1044,7 @@ } void SessionStorageImpl::OnReceiverDisconnected() { - ShutDown(base::DoNothing()); - service_->RemoveSessionStorage(this); + std::move(destruct_callback_).Run(this); } } // namespace storage
diff --git a/components/services/storage/dom_storage/session_storage_impl.h b/components/services/storage/dom_storage/session_storage_impl.h index 81a2df9..848a041 100644 --- a/components/services/storage/dom_storage/session_storage_impl.h +++ b/components/services/storage/dom_storage/session_storage_impl.h
@@ -67,13 +67,15 @@ kRestoreDiskState }; + using DestructSessionStorageCallback = + base::OnceCallback<void(SessionStorageImpl*)>; SessionStorageImpl( - StorageServiceImpl& service, const base::FilePath& partition_directory, scoped_refptr<base::SequencedTaskRunner> blocking_task_runner, scoped_refptr<base::SequencedTaskRunner> memory_dump_task_runner, BackingMode backing_option, std::string database_name, + DestructSessionStorageCallback destruct_callback, mojo::PendingReceiver<mojom::SessionStorageControl> receiver); ~SessionStorageImpl() override; @@ -243,8 +245,10 @@ void OnReceiverDisconnected(); - // The StorageServiceImpl that owns this object. - const raw_ref<StorageServiceImpl> service_; + // Passed in by the StorageServiceImpl that owns this object. Used to signal + // that this SessionStorageImpl can be destructed when the Receiver is + // disconnected. + DestructSessionStorageCallback destruct_callback_; // Since the session storage object hierarchy references iterators owned by // the metadata, make sure it is destroyed last on destruction. SessionStorageMetadata metadata_;
diff --git a/components/services/storage/dom_storage/session_storage_impl_unittest.cc b/components/services/storage/dom_storage/session_storage_impl_unittest.cc index f7658eca..e866928 100644 --- a/components/services/storage/dom_storage/session_storage_impl_unittest.cc +++ b/components/services/storage/dom_storage/session_storage_impl_unittest.cc
@@ -29,7 +29,6 @@ #include "components/services/storage/dom_storage/storage_area_test_util.h" #include "components/services/storage/dom_storage/testing_legacy_session_storage_database.h" #include "components/services/storage/public/mojom/storage_service.mojom.h" -#include "components/services/storage/storage_service_impl.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/system/functions.h" #include "testing/gtest/include/gtest/gtest.h" @@ -88,9 +87,9 @@ if (!session_storage_) { remote_session_storage_.reset(); session_storage_ = std::make_unique<SessionStorageImpl>( - storage_service_, temp_path(), blocking_task_runner_, + temp_path(), blocking_task_runner_, base::SequencedTaskRunner::GetCurrentDefault(), backing_mode_, - kSessionStorageDirectory, + kSessionStorageDirectory, base::DoNothing(), remote_session_storage_.BindNewPipeAndPassReceiver()); } return session_storage_.get(); @@ -159,10 +158,6 @@ private: base::test::TaskEnvironment task_environment_; - mojo::Remote<mojom::StorageService> remote_service_; - StorageServiceImpl storage_service_{ - remote_service_.BindNewPipeAndPassReceiver(), - /*io_task_runner=*/nullptr}; base::ScopedTempDir temp_dir_; SessionStorageImpl::BackingMode backing_mode_ = SessionStorageImpl::BackingMode::kRestoreDiskState;
diff --git a/components/services/storage/storage_service_impl.cc b/components/services/storage/storage_service_impl.cc index ec489d3a..21ee21c 100644 --- a/components/services/storage/storage_service_impl.cc +++ b/components/services/storage/storage_service_impl.cc
@@ -5,6 +5,7 @@ #include "components/services/storage/storage_service_impl.h" #include "base/functional/bind.h" +#include "base/not_fatal_until.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "build/build_config.h" @@ -50,6 +51,27 @@ } #endif +template <typename T> +base::OnceClosure MakeDeferredDeleter(std::unique_ptr<T> object) { + return base::BindOnce( + [](scoped_refptr<base::SequencedTaskRunner> task_runner, T* object) { + task_runner->DeleteSoon(FROM_HERE, object); + }, + base::SequencedTaskRunner::GetCurrentDefault(), + // NOTE: We release `object` immediately. In the case + // where this task never runs, we prefer to leak the + // object rather than potentially destroying it on the + // wrong sequence. + object.release()); +} + +template <typename T> +void ShutDown(std::unique_ptr<T> object) { + if (T* ptr = object.get()) { + ptr->ShutDown(MakeDeferredDeleter(std::move(object))); + } +} + } // namespace StorageServiceImpl::StorageServiceImpl( @@ -59,12 +81,17 @@ io_task_runner_(std::move(io_task_runner)) {} StorageServiceImpl::~StorageServiceImpl() { - // Shut down storages before we destroy the service. - for (const auto& local_storage : local_storages_) { - local_storage->ShutDown(base::DoNothing()); + // ShutDown storages before we destroy the service. We transfer ownership of + // the storages to the ShutDown function, which deletes them after ShutDown + // completes. + while (!local_storages_.empty()) { + auto node = local_storages_.extract(local_storages_.begin()); + ShutDown(std::move(node.value())); } - for (const auto& session_storage : session_storages_) { - session_storage->ShutDown(base::DoNothing()); + + while (!session_storages_.empty()) { + auto node = session_storages_.extract(session_storages_.begin()); + ShutDown(std::move(node.value())); } } @@ -107,15 +134,24 @@ return; } + auto iter = persistent_local_storage_map_.find(*path); + bool found = iter != persistent_local_storage_map_.end(); // The map shouldn't contain an entry for this path. We should only bind a // LocalStorage mojom::Receiver once. - auto iter = persistent_local_storage_map_.find(*path); - CHECK(iter == persistent_local_storage_map_.end()); + CHECK(!found, base::NotFatalUntil::M140); + // TODO(crbug.com/396030877): Remove this workaround to remove the + // pre-existing LocalStorage once the issue is resolved. + if (found) { + ShutDownAndRemoveLocalStorage(iter->second); + } } auto new_local_storage = std::make_unique<LocalStorageImpl>( - *this, path.value_or(base::FilePath()), - base::SequencedTaskRunner::GetCurrentDefault(), std::move(receiver)); + path.value_or(base::FilePath()), + base::SequencedTaskRunner::GetCurrentDefault(), + base::BindOnce(&StorageServiceImpl::ShutDownAndRemoveLocalStorage, + weak_ptr_factory_.GetWeakPtr()), + std::move(receiver)); if (path.has_value()) { persistent_local_storage_map_[*path] = new_local_storage.get(); } @@ -131,14 +167,20 @@ return; } - // The map shouldn't contain an entry for this path. We should only bind to - // a SessionStorage mojom::Receiver once. auto iter = persistent_session_storage_map_.find(*path); - CHECK(iter == persistent_session_storage_map_.end()); + bool found = iter != persistent_session_storage_map_.end(); + // The map shouldn't contain an entry for this path. We should only bind a + // SessionStorage mojom::Receiver once. + CHECK(!found, base::NotFatalUntil::M140); + // TODO(crbug.com/396030877): Remove this workaround to remove the + // pre-existing SessionStorage once the issue is resolved. + if (found) { + ShutDownAndRemoveSessionStorage(iter->second); + } } auto new_session_storage = std::make_unique<SessionStorageImpl>( - *this, path.value_or(base::FilePath()), + path.value_or(base::FilePath()), base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::WithBaseSyncPrimitives(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN}), @@ -152,7 +194,11 @@ path.has_value() ? SessionStorageImpl::BackingMode::kRestoreDiskState : SessionStorageImpl::BackingMode::kNoDisk, #endif - std::string(kSessionStorageDirectory), std::move(receiver)); + std::string(kSessionStorageDirectory), + base::OnceCallback<void(SessionStorageImpl*)>( + base::BindOnce(&StorageServiceImpl::ShutDownAndRemoveSessionStorage, + weak_ptr_factory_.GetWeakPtr())), + std::move(receiver)); if (path.has_value()) { persistent_session_storage_map_[*path] = new_session_storage.get(); } @@ -164,25 +210,29 @@ GetTestApiBinderForTesting().Run(std::move(test_api_receiver)); } -void StorageServiceImpl::RemoveSessionStorage(SessionStorageImpl* storage) { +void StorageServiceImpl::ShutDownAndRemoveSessionStorage( + SessionStorageImpl* storage) { if (!storage->GetStoragePath().empty()) { persistent_session_storage_map_.erase(storage->GetStoragePath()); } auto it = session_storages_.find(storage); if (it != session_storages_.end()) { - session_storages_.erase(it); + auto node = session_storages_.extract(it); + ShutDown(std::move(node.value())); } } -void StorageServiceImpl::RemoveLocalStorage(LocalStorageImpl* storage) { +void StorageServiceImpl::ShutDownAndRemoveLocalStorage( + LocalStorageImpl* storage) { if (!storage->GetStoragePath().empty()) { persistent_local_storage_map_.erase(storage->GetStoragePath()); } auto it = local_storages_.find(storage); if (it != local_storages_.end()) { - local_storages_.erase(it); + auto node = local_storages_.extract(it); + ShutDown(std::move(node.value())); } }
diff --git a/components/services/storage/storage_service_impl.h b/components/services/storage/storage_service_impl.h index 7a464fc..705d021 100644 --- a/components/services/storage/storage_service_impl.h +++ b/components/services/storage/storage_service_impl.h
@@ -56,8 +56,13 @@ mojo::PendingReceiver<mojom::SessionStorageControl> receiver) override; void BindTestApi(mojo::ScopedMessagePipeHandle test_api_receiver) override; - void RemoveSessionStorage(SessionStorageImpl* storage); - void RemoveLocalStorage(LocalStorageImpl* storage); + // These transfer ownership of the storage instance to a DeferredDeleter when + // performing ShutDown. This allows the storage instance to be deleted after + // ShutDown is complete. This prevents race conditions where a storage + // instance for a user data directory is rebound while we wait for the + // previous instance to ShutDown. + void ShutDownAndRemoveSessionStorage(SessionStorageImpl* storage); + void ShutDownAndRemoveLocalStorage(LocalStorageImpl* storage); private: #if !BUILDFLAG(IS_ANDROID)
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc index 4f7bd93..323144d 100644 --- a/components/signin/public/base/signin_switches.cc +++ b/components/signin/public/base/signin_switches.cc
@@ -49,11 +49,11 @@ "SkipCheckForAccountManagementOnSignin", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kUnoForAuto, "UnoForAuto", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kUnoForAuto, "UnoForAuto", base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kUseHostedDomainForManagementCheckOnSignin, "UseHostedDomainForManagementCheckOnSignin", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kMakeAccountsAvailableInIdentityManager, "MakeAccountsAvailableInIdentityManager",
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index 11f1385..5fe4fd8 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -283,6 +283,7 @@ "//components/version_info", "//components/version_info:generate_version_info", "//components/version_info:version_string", + "//extensions/buildflags", "//google_apis:test_support", "//google_apis/gcm:gcm", "//net",
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc index 880e487..07f5bea2 100644 --- a/components/sync/base/features.cc +++ b/components/sync/base/features.cc
@@ -23,7 +23,7 @@ #if BUILDFLAG(IS_ANDROID) BASE_FEATURE(kUnoPhase2FollowUp, "UnoPhase2FollowUp", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) BASE_FEATURE(kSyncAutofillWalletCredentialData,
diff --git a/components/sync/service/BUILD.gn b/components/sync/service/BUILD.gn index 618c38f..b57275c 100644 --- a/components/sync/service/BUILD.gn +++ b/components/sync/service/BUILD.gn
@@ -118,6 +118,7 @@ "//components/version_info", "//components/version_info:generate_version_info", "//crypto", + "//extensions/buildflags", "//services/network/public/cpp", "//ui/base", ]
diff --git a/components/sync/service/DEPS b/components/sync/service/DEPS index 48cfed33..298cbd2 100644 --- a/components/sync/service/DEPS +++ b/components/sync/service/DEPS
@@ -19,6 +19,7 @@ "+components/trusted_vault", "+components/url_formatter", "+crypto", + "+extensions/buildflags", "+net", "+services/network/public/cpp", "+services/network/public/mojom",
diff --git a/components/sync/service/sync_prefs.cc b/components/sync/service/sync_prefs.cc index ac14db81..b22803a 100644 --- a/components/sync/service/sync_prefs.cc +++ b/components/sync/service/sync_prefs.cc
@@ -36,6 +36,7 @@ #include "components/sync/protocol/nigori_specifics.pb.h" #include "components/sync/service/glue/sync_transport_data_prefs.h" #include "components/sync/service/sync_feature_status_for_migrations_recorder.h" +#include "extensions/buildflags/buildflags.h" #include "google_apis/gaia/gaia_id.h" namespace syncer { @@ -745,8 +746,12 @@ case UserSelectableType::kSavedTabGroups: return base::FeatureList::IsEnabled(kReplaceSyncPromosWithSignInPromos); case UserSelectableType::kExtensions: +#if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) + return true; +#else return base::FeatureList::IsEnabled( switches::kEnableExtensionsExplicitBrowserSignin); +#endif case UserSelectableType::kThemes: #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) return false;
diff --git a/components/sync/service/sync_prefs_unittest.cc b/components/sync/service/sync_prefs_unittest.cc index 2a2413fb4..2e5375e 100644 --- a/components/sync/service/sync_prefs_unittest.cc +++ b/components/sync/service/sync_prefs_unittest.cc
@@ -24,6 +24,7 @@ #include "components/sync/base/user_selectable_type.h" #include "components/sync/protocol/nigori_specifics.pb.h" #include "components/sync/service/glue/sync_transport_data_prefs.h" +#include "extensions/buildflags/buildflags.h" #include "google_apis/gaia/gaia_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/test/data/enterprise/watermark_dark.png b/components/test/data/enterprise/watermark_dark.png index 1a55c93bd..bc10f57 100644 --- a/components/test/data/enterprise/watermark_dark.png +++ b/components/test/data/enterprise/watermark_dark.png Binary files differ
diff --git a/components/test/data/enterprise/watermark_light.png b/components/test/data/enterprise/watermark_light.png index 978ef0e..6dc2e43 100644 --- a/components/test/data/enterprise/watermark_light.png +++ b/components/test/data/enterprise/watermark_light.png Binary files differ
diff --git a/components/tracing/common/tracing_scenarios_config.cc b/components/tracing/common/tracing_scenarios_config.cc index f0ab4d43..c2aa383 100644 --- a/components/tracing/common/tracing_scenarios_config.cc +++ b/components/tracing/common/tracing_scenarios_config.cc
@@ -150,6 +150,8 @@ "'Help > Report an Issue'."); scenario->add_start_rules()->set_manual_trigger_name("startup"); scenario->add_start_rules()->set_delay_ms(1); + scenario->add_start_rules()->set_manual_trigger_name("incognito-end"); + scenario->add_stop_rules()->set_manual_trigger_name("incognito-start"); auto* nested_scenario = scenario->add_nested_scenarios(); nested_scenario->set_scenario_name("AlwaysOnScenario.Snapshots"); nested_scenario->add_start_rules()->set_delay_ms(1);
diff --git a/components/variations/variations_associated_data.cc b/components/variations/variations_associated_data.cc index 97038eb..a67dbb4e 100644 --- a/components/variations/variations_associated_data.cc +++ b/components/variations/variations_associated_data.cc
@@ -114,6 +114,28 @@ } } + base::Time GetNextTimeWindowEvent(base::Time current_time) const { + base::AutoLock scoped_lock(lock_); + base::Time next_event = base::Time::Max(); + // This double loop is O(N) where N is the number of field trials having an + // associated variations ID, which should be in the order of 10s at most. + for (const auto& id_map : group_to_id_maps_) { + for (const auto& [id, entry] : id_map) { + // Update the next time window event if the start or end time is after + // 'now' but also before `next_time_window_event_`. + if (entry.time_window.start() > current_time && + entry.time_window.start() < next_event) { + next_event = entry.time_window.start(); + } + if (entry.time_window.end() > current_time && + entry.time_window.end() < next_event) { + next_event = entry.time_window.end(); + } + } + } + return next_event; + } + private: friend struct base::DefaultSingletonTraits<GroupMapAccessor>; @@ -125,7 +147,7 @@ GroupMapAccessor() { group_to_id_maps_.resize(ID_COLLECTION_COUNT); } ~GroupMapAccessor() = default; - base::Lock lock_; + mutable base::Lock lock_; std::vector<GroupToIDMap> group_to_id_maps_; }; @@ -178,6 +200,10 @@ current_time); } +base::Time GetNextTimeWindowEvent(base::Time current_time) { + return GroupMapAccessor::GetInstance()->GetNextTimeWindowEvent(current_time); +} + // Functions below are exposed for testing explicitly behind this namespace. // They simply wrap existing functions in this file. namespace testing {
diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h index 4b760d5e..f30984a4 100644 --- a/components/variations/variations_associated_data.h +++ b/components/variations/variations_associated_data.h
@@ -159,6 +159,10 @@ ActiveGroupId active_group, std::optional<base::Time> current_time = std::nullopt); +// Given `current_time`, returns the next time that a time windows will start or +// end for a VariationID. +COMPONENT_EXPORT(VARIATIONS) +base::Time GetNextTimeWindowEvent(base::Time current_time); // Expose some functions for testing. namespace testing {
diff --git a/components/variations/variations_associated_data_unittest.cc b/components/variations/variations_associated_data_unittest.cc index e96c97e..e0e5710 100644 --- a/components/variations/variations_associated_data_unittest.cc +++ b/components/variations/variations_associated_data_unittest.cc
@@ -5,6 +5,8 @@ #include "components/variations/variations_associated_data.h" #include "base/metrics/field_trial.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/test/mock_entropy_provider.h" #include "testing/gtest/include/gtest/gtest.h" @@ -158,4 +160,64 @@ GetGoogleVariationID(APP, TRIAL, GROUP, end + base::Days(15))); } +TEST_F(VariationsAssociatedDataTest, GetNextTimeWindowEvent_Basic) { + const base::Time timestamp = base::Time::Now(); + const base::Time start = timestamp + base::Days(7); + const base::Time end = timestamp + base::Days(14); + + EXPECT_EQ(base::Time::Max(), GetNextTimeWindowEvent(start)); + EXPECT_EQ(base::Time::Max(), GetNextTimeWindowEvent(end)); + + // Associate a variation id that becomes visible in 7 days, for 7 days. + AssociateGoogleVariationID(APP, TRIAL, GROUP, TEST_VALUE_A, {start, end}); + + // Validate the next time window event as 'current_time' moves forward. + EXPECT_EQ(start, GetNextTimeWindowEvent(start - base::Days(1))); + EXPECT_EQ(start, GetNextTimeWindowEvent(start - base::Seconds(1))); + EXPECT_EQ(end, GetNextTimeWindowEvent(start)); + EXPECT_EQ(end, GetNextTimeWindowEvent(end - base::Days(1))); + EXPECT_EQ(end, GetNextTimeWindowEvent(end - base::Seconds(1))); + EXPECT_EQ(base::Time::Max(), GetNextTimeWindowEvent(end)); + EXPECT_EQ(base::Time::Max(), GetNextTimeWindowEvent(end + base::Seconds(1))); +} + +TEST_F(VariationsAssociatedDataTest, + GetNextTimeWindowEvent_DisjointAndOverlapping) { + const base::Time timestamp = base::Time::Now(); + + const TimeWindow windows[] = { + {timestamp + base::Days(3), timestamp + base::Days(6)}, // Disjoint. + {timestamp + base::Days(7), timestamp + base::Days(14)}, // Overlapped. + {timestamp + base::Days(9), timestamp + base::Days(11)}, // Contained. + {timestamp + base::Days(10), timestamp + base::Days(16)}, // Partial. + }; + + // Associate a variation id for each time window. + int i = 0; + for (const auto& window : windows) { + AssociateGoogleVariationID( + APP, base::StrCat({TRIAL, "_", base::NumberToString(i)}), GROUP, + TEST_VALUE_A + i, window); + ++i; + } + + // Put all of the time window events into vector, then sort that vector. This + // is the order that GetNextTimeWindowEvent() should return them. + std::vector<base::Time> times; + for (const auto& window : windows) { + times.push_back(window.start()); + times.push_back(window.end()); + } + std::sort(times.begin(), times.end()); + + // Validate that the next time window event is always the next event in the + // sorted event list. + base::Time prev = base::Time::Min(); + for (const auto& time : times) { + EXPECT_EQ(time, GetNextTimeWindowEvent(prev)); + prev = time; + } + EXPECT_EQ(base::Time::Max(), GetNextTimeWindowEvent(prev)); +} + } // namespace variations
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc index acec916..68a23d2 100644 --- a/components/viz/common/features.cc +++ b/components/viz/common/features.cc
@@ -582,7 +582,9 @@ // can take the Swiftshader rendering path, which also needs the Redirection // Bitmap. On devices with DComp disabled, ANGLE draws to the redirection // bitmap via a blit swap chain, so check for the command line switch as well. - return base::win::GetVersion() >= base::win::Version::WIN11 && + // 22H2 is specified because it is the lowest version supporting DWM system + // backdrop. + return base::win::GetVersion() >= base::win::Version::WIN11_22H2 && base::FeatureList::IsEnabled(kRemoveRedirectionBitmap) && !base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kOverrideUseSoftwareGLForTests) &&
diff --git a/components/webcrypto/algorithm_implementation.cc b/components/webcrypto/algorithm_implementation.cc index 4bdc0ca..583f89f 100644 --- a/components/webcrypto/algorithm_implementation.cc +++ b/components/webcrypto/algorithm_implementation.cc
@@ -8,6 +8,7 @@ #include "components/webcrypto/algorithms/asymmetric_key_util.h" #include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" namespace webcrypto { @@ -100,21 +101,13 @@ return Status::Success(); case blink::kWebCryptoKeyTypePublic: { - std::vector<uint8_t> vec; - Status status = ExportPKeySpki(GetEVP_PKEY(key), &vec); - if (status.IsSuccess()) { - *key_data = vec; - } - return status; + *key_data = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } case blink::kWebCryptoKeyTypePrivate: { - std::vector<uint8_t> vec; - Status status = ExportPKeyPkcs8(GetEVP_PKEY(key), &vec); - if (status.IsSuccess()) { - *key_data = vec; - } - return status; + *key_data = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } } NOTREACHED();
diff --git a/components/webcrypto/algorithms/asymmetric_key_util.cc b/components/webcrypto/algorithms/asymmetric_key_util.cc index 0d27fb2..815e95e 100644 --- a/components/webcrypto/algorithms/asymmetric_key_util.cc +++ b/components/webcrypto/algorithms/asymmetric_key_util.cc
@@ -2,60 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "components/webcrypto/algorithms/asymmetric_key_util.h" #include <stdint.h> + #include <utility> #include "components/webcrypto/algorithms/util.h" #include "components/webcrypto/blink_key_handle.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" -#include "third_party/boringssl/src/include/openssl/bytestring.h" #include "third_party/boringssl/src/include/openssl/evp.h" -#include "third_party/boringssl/src/include/openssl/mem.h" namespace webcrypto { -// Exports an EVP_PKEY public key to the SPKI format. -Status ExportPKeySpki(EVP_PKEY* key, std::vector<uint8_t>* buffer) { - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - - uint8_t* der; - size_t der_len; - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || !EVP_marshal_public_key(cbb.get(), key) || - !CBB_finish(cbb.get(), &der, &der_len)) { - return Status::ErrorUnexpected(); - } - buffer->assign(der, der + der_len); - OPENSSL_free(der); - return Status::Success(); -} - -// Exports an EVP_PKEY private key to the PKCS8 format. -Status ExportPKeyPkcs8(EVP_PKEY* key, std::vector<uint8_t>* buffer) { - crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - - // TODO(eroman): Use the OID specified by webcrypto spec. - // http://crbug.com/373545 - uint8_t* der; - size_t der_len; - bssl::ScopedCBB cbb; - if (!CBB_init(cbb.get(), 0) || !EVP_marshal_private_key(cbb.get(), key) || - !CBB_finish(cbb.get(), &der, &der_len)) { - return Status::ErrorUnexpected(); - } - buffer->assign(der, der + der_len); - OPENSSL_free(der); - return Status::Success(); -} - Status CreateWebCryptoPublicKey(bssl::UniquePtr<EVP_PKEY> public_key, const blink::WebCryptoKeyAlgorithm& algorithm, bool extractable, @@ -83,11 +44,10 @@ bssl::UniquePtr<EVP_PKEY>* out_pkey) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - CBS cbs; - CBS_init(&cbs, key_data.data(), key_data.size()); - bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs)); - if (!pkey || CBS_len(&cbs) != 0) + bssl::UniquePtr<EVP_PKEY> pkey = crypto::evp::PublicKeyFromBytes(key_data); + if (!pkey) { return Status::DataError(); + } if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) return Status::DataError(); // Data did not define expected key type. @@ -101,11 +61,10 @@ bssl::UniquePtr<EVP_PKEY>* out_pkey) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - CBS cbs; - CBS_init(&cbs, key_data.data(), key_data.size()); - bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs)); - if (!pkey || CBS_len(&cbs) != 0) + bssl::UniquePtr<EVP_PKEY> pkey = crypto::evp::PrivateKeyFromBytes(key_data); + if (!pkey) { return Status::DataError(); + } if (EVP_PKEY_id(pkey.get()) != expected_pkey_id) return Status::DataError(); // Data did not define expected key type.
diff --git a/components/webcrypto/algorithms/ec.cc b/components/webcrypto/algorithms/ec.cc index 0a7b6167..caaf3f2 100644 --- a/components/webcrypto/algorithms/ec.cc +++ b/components/webcrypto/algorithms/ec.cc
@@ -21,6 +21,7 @@ #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "third_party/blink/public/platform/web_crypto_algorithm_params.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" @@ -584,14 +585,16 @@ std::vector<uint8_t>* buffer) const { if (key.GetType() != blink::kWebCryptoKeyTypePrivate) return Status::ErrorUnexpectedKeyType(); - return ExportPKeyPkcs8(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status EcAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, std::vector<uint8_t>* buffer) const { if (key.GetType() != blink::kWebCryptoKeyTypePublic) return Status::ErrorUnexpectedKeyType(); - return ExportPKeySpki(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } // The format for JWK EC keys is given by:
diff --git a/components/webcrypto/algorithms/ed25519.cc b/components/webcrypto/algorithms/ed25519.cc index f9b164d..a640d7e5 100644 --- a/components/webcrypto/algorithms/ed25519.cc +++ b/components/webcrypto/algorithms/ed25519.cc
@@ -19,6 +19,7 @@ #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" #include "third_party/boringssl/src/include/openssl/bytestring.h" @@ -408,7 +409,8 @@ if (key.GetType() != blink::kWebCryptoKeyTypePrivate) return Status::ErrorUnexpectedKeyType(); - return ExportPKeyPkcs8(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status Ed25519Implementation::ExportKeySpki( @@ -417,7 +419,8 @@ if (key.GetType() != blink::kWebCryptoKeyTypePublic) return Status::ErrorUnexpectedKeyType(); - return ExportPKeySpki(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status Ed25519Implementation::ExportKeyJwk(const blink::WebCryptoKey& key,
diff --git a/components/webcrypto/algorithms/rsa.cc b/components/webcrypto/algorithms/rsa.cc index 527f0f7..1c6e0fa 100644 --- a/components/webcrypto/algorithms/rsa.cc +++ b/components/webcrypto/algorithms/rsa.cc
@@ -9,9 +9,8 @@ #include "components/webcrypto/algorithms/rsa.h" -#include <utility> - #include <string_view> +#include <utility> #include "base/check_op.h" #include "base/containers/span.h" @@ -21,6 +20,7 @@ #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "third_party/blink/public/platform/web_crypto_algorithm_params.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" @@ -482,14 +482,16 @@ std::vector<uint8_t>* buffer) const { if (key.GetType() != blink::kWebCryptoKeyTypePrivate) return Status::ErrorUnexpectedKeyType(); - return ExportPKeyPkcs8(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status RsaHashedAlgorithm::ExportKeySpki(const blink::WebCryptoKey& key, std::vector<uint8_t>* buffer) const { if (key.GetType() != blink::kWebCryptoKeyTypePublic) return Status::ErrorUnexpectedKeyType(); - return ExportPKeySpki(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status RsaHashedAlgorithm::ExportKeyJwk(const blink::WebCryptoKey& key,
diff --git a/components/webcrypto/algorithms/x25519.cc b/components/webcrypto/algorithms/x25519.cc index 32af31a..dbc7b5c 100644 --- a/components/webcrypto/algorithms/x25519.cc +++ b/components/webcrypto/algorithms/x25519.cc
@@ -17,6 +17,7 @@ #include "components/webcrypto/generate_key_result.h" #include "components/webcrypto/jwk.h" #include "components/webcrypto/status.h" +#include "crypto/evp.h" #include "crypto/openssl_util.h" #include "third_party/blink/public/platform/web_crypto_algorithm_params.h" #include "third_party/blink/public/platform/web_crypto_key_algorithm.h" @@ -429,7 +430,8 @@ return Status::ErrorUnexpectedKeyType(); } - return ExportPKeyPkcs8(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PrivateKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status X25519Implementation::ExportKeySpki(const blink::WebCryptoKey& key, @@ -438,7 +440,8 @@ return Status::ErrorUnexpectedKeyType(); } - return ExportPKeySpki(GetEVP_PKEY(key), buffer); + *buffer = crypto::evp::PublicKeyToBytes(GetEVP_PKEY(key)); + return Status::Success(); } Status X25519Implementation::ExportKeyJwk(const blink::WebCryptoKey& key,
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 27f22d4..de449fc8 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -104,6 +104,14 @@ return ui::BrowserAccessibilityManager::GetFocus(); } +ui::BrowserAccessibility* +BrowserAccessibilityManagerAndroid::GetAccessibilityFocus() const { + if (auto* wcax = GetWebContentsAXFromRootManager()) { + return wcax->GetAccessibilityFocus(); + } + return nullptr; +} + ui::AXNode* BrowserAccessibilityManagerAndroid::RetargetForEvents( ui::AXNode* node, RetargetEventType type) const { @@ -728,7 +736,7 @@ } WebContentsAccessibilityAndroid* -BrowserAccessibilityManagerAndroid::GetWebContentsAXFromRootManager() { +BrowserAccessibilityManagerAndroid::GetWebContentsAXFromRootManager() const { ui::BrowserAccessibility* parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility(); if (!parent_node) {
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h index 6f36e6d..ca41cdf 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.h +++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -111,6 +111,7 @@ // BrowserAccessibilityManager overrides. ui::BrowserAccessibility* GetFocus() const override; + ui::BrowserAccessibility* GetAccessibilityFocus() const override; void SendLocationChangeEvents( const std::vector<ui::AXLocationChange>& changes) override; ui::AXNode* RetargetForEvents(ui::AXNode* node, @@ -169,7 +170,7 @@ bool root_changed, const std::vector<ui::AXTreeObserver::Change>& changes) override; - WebContentsAccessibilityAndroid* GetWebContentsAXFromRootManager(); + WebContentsAccessibilityAndroid* GetWebContentsAXFromRootManager() const; // This gives BrowserAccessibilityManager::Create access to the class // constructor.
diff --git a/content/browser/accessibility/web_contents_accessibility_android.cc b/content/browser/accessibility/web_contents_accessibility_android.cc index 74e0542..5c0af34 100644 --- a/content/browser/accessibility/web_contents_accessibility_android.cc +++ b/content/browser/accessibility/web_contents_accessibility_android.cc
@@ -779,6 +779,17 @@ allow_image_descriptions_ = allow_image_descriptions; } +BrowserAccessibilityAndroid* +WebContentsAccessibilityAndroid::GetAccessibilityFocus() const { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) { + return nullptr; + } + jint id = Java_WebContentsAccessibilityImpl_getAccessibilityFocusId(env, obj); + return GetAXFromUniqueID(id); +} + void WebContentsAccessibilityAndroid::HandleContentChanged(int32_t unique_id) { JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); @@ -1332,29 +1343,40 @@ bool is_link = ui::IsLink(node->GetRole()); if (::features::IsAccessibilityTextFormattingEnabled()) { - // TODO: aluh - Limit to accessibility focus. - AXStyleData style_data; - std::u16string text = - node->GetSubstringTextContentUTF16(std::nullopt, &style_data); + std::unique_ptr<AXStyleData> style_data; + if (auto* manager = GetRootBrowserAccessibilityManager()) { + if (auto* focus = static_cast<BrowserAccessibilityAndroid*>( + manager->GetAccessibilityFocus()); + focus == node) { + style_data = std::make_unique<AXStyleData>(); + } + } - ScopedJavaLocalRef<jobject> java_suggestions = - ToJavaStringRangesMap(env, style_data.suggestions); - ScopedJavaLocalRef<jobject> java_links = - ToJavaStringRangesMap(env, style_data.links); - ScopedJavaLocalRef<jobject> java_text_sizes = - ToJavaFloatRangesMap(env, style_data.text_sizes); - ScopedJavaLocalRef<jobject> java_text_styles = - ToJavaIntRangesMap(env, style_data.text_styles); - ScopedJavaLocalRef<jobject> java_text_positions = - ToJavaIntRangesMap(env, style_data.text_positions); - ScopedJavaLocalRef<jobject> java_foreground_colors = - ToJavaIntRangesMap(env, style_data.foreground_colors); - ScopedJavaLocalRef<jobject> java_background_colors = - ToJavaIntRangesMap(env, style_data.background_colors); - ScopedJavaLocalRef<jobject> java_font_families = - ToJavaCanonicalStringRangesMap(env, style_data.font_families); - ScopedJavaLocalRef<jobject> java_locales = - ToJavaCanonicalStringRangesMap(env, style_data.locales); + std::u16string text = node->GetSubstringTextContentUTF16( + /*min_length=*/std::nullopt, style_data.get()); + + ScopedJavaLocalRef<jobject> java_suggestions; + ScopedJavaLocalRef<jobject> java_links; + ScopedJavaLocalRef<jobject> java_text_sizes; + ScopedJavaLocalRef<jobject> java_text_styles; + ScopedJavaLocalRef<jobject> java_text_positions; + ScopedJavaLocalRef<jobject> java_fg_colors; + ScopedJavaLocalRef<jobject> java_bg_colors; + ScopedJavaLocalRef<jobject> java_font_families; + ScopedJavaLocalRef<jobject> java_locales; + + if (style_data) { + java_suggestions = ToJavaStringRangesMap(env, style_data->suggestions); + java_links = ToJavaStringRangesMap(env, style_data->links); + java_text_sizes = ToJavaFloatRangesMap(env, style_data->text_sizes); + java_text_styles = ToJavaIntRangesMap(env, style_data->text_styles); + java_text_positions = ToJavaIntRangesMap(env, style_data->text_positions); + java_fg_colors = ToJavaIntRangesMap(env, style_data->foreground_colors); + java_bg_colors = ToJavaIntRangesMap(env, style_data->background_colors); + java_font_families = + ToJavaCanonicalStringRangesMap(env, style_data->font_families); + java_locales = ToJavaCanonicalStringRangesMap(env, style_data->locales); + } Java_AccessibilityNodeInfoBuilder_setAccessibilityNodeInfoText( env, obj, info, base::android::ConvertUTF16ToJavaString(env, text), @@ -1367,8 +1389,8 @@ base::android::ConvertUTF16ToJavaString( env, node->GetSupplementalDescription()), java_suggestions, java_links, java_text_sizes, java_text_styles, - java_text_positions, java_foreground_colors, java_background_colors, - java_font_families, java_locales); + java_text_positions, java_fg_colors, java_bg_colors, java_font_families, + java_locales); } else { ScopedJavaLocalRef<jintArray> java_suggestion_starts; ScopedJavaLocalRef<jintArray> java_suggestion_ends; @@ -2151,7 +2173,7 @@ } BrowserAccessibilityManagerAndroid* -WebContentsAccessibilityAndroid::GetRootBrowserAccessibilityManager() { +WebContentsAccessibilityAndroid::GetRootBrowserAccessibilityManager() const { if (snapshot_root_manager_) { return snapshot_root_manager_.get(); } @@ -2161,7 +2183,7 @@ } BrowserAccessibilityAndroid* WebContentsAccessibilityAndroid::GetAXFromUniqueID( - int32_t unique_id) { + int32_t unique_id) const { return BrowserAccessibilityAndroid::GetFromUniqueId(unique_id); }
diff --git a/content/browser/accessibility/web_contents_accessibility_android.h b/content/browser/accessibility/web_contents_accessibility_android.h index d144459..42313f7 100644 --- a/content/browser/accessibility/web_contents_accessibility_android.h +++ b/content/browser/accessibility/web_contents_accessibility_android.h
@@ -383,6 +383,8 @@ return allow_image_descriptions_; } + BrowserAccessibilityAndroid* GetAccessibilityFocus() const; + void HandlePageLoaded(int32_t unique_id); void HandleContentChanged(int32_t unique_id); void HandleFocusChanged(int32_t unique_id); @@ -414,9 +416,10 @@ WebContentsAccessibilityAndroid(); - BrowserAccessibilityManagerAndroid* GetRootBrowserAccessibilityManager(); + BrowserAccessibilityManagerAndroid* GetRootBrowserAccessibilityManager() + const; - BrowserAccessibilityAndroid* GetAXFromUniqueID(int32_t unique_id); + BrowserAccessibilityAndroid* GetAXFromUniqueID(int32_t unique_id) const; void UpdateAccessibilityNodeInfoBoundsRect( JNIEnv* env,
diff --git a/content/browser/android/app_web_message_port.cc b/content/browser/android/app_web_message_port.cc index a262ea04..8e46c2a 100644 --- a/content/browser/android/app_web_message_port.cc +++ b/content/browser/android/app_web_message_port.cc
@@ -114,10 +114,10 @@ transferable_message.ports = blink::MessagePortChannel::CreateFromHandles(Release(env, j_ports)); // As the message is posted from an Android app and not from another renderer, - // set the agent cluster ID to the embedder's, and nullify its parent task ID. + // set the agent cluster ID to the embedder's, and nullify its task state ID. transferable_message.sender_agent_cluster_id = blink::WebMessagePort::GetEmbedderAgentClusterID(); - transferable_message.parent_task_id = std::nullopt; + transferable_message.task_state_id = std::nullopt; mojo::Message mojo_message = blink::mojom::TransferableMessage::SerializeAsMessage(
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc index 805e5e5..07e9b497 100644 --- a/content/browser/network_service_browsertest.cc +++ b/content/browser/network_service_browsertest.cc
@@ -649,9 +649,8 @@ EXPECT_TRUE(test_loader_factory->has_received_request()); } -// Android doesn't support PRE_ tests. -// TODO(wfh): Enable this test when https://crbug.com/1257820 is fixed. -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_FUCHSIA) +// Cache data migration is not used for Fuchsia. +#if !BUILDFLAG(IS_FUCHSIA) class NetworkServiceBrowserCacheResetTest : public NetworkServiceBrowserTest { public: NetworkServiceBrowserCacheResetTest() = default; @@ -824,10 +823,6 @@ net::test::IsError(net::ERR_CACHE_MISS)); } #endif // BUILDFLAG(IS_POSIX) -#endif // BUILDFLAG(IS_ANDROID) - -// Cache data migration is not used for Fuchsia. -#if !BUILDFLAG(IS_FUCHSIA) const base::FilePath::CharType kCheckpointFileName[] = FILE_PATH_LITERAL("NetworkDataMigrated");
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index f88b7f3..6688eb0 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -545,7 +545,8 @@ ->AddPrefetchContainerWithHandle(std::move(prefetch_container)); } - std::unique_ptr<content::PrefetchHandle> MakePrefetchFromBrowserContext( + [[nodiscard]] std::unique_ptr<content::PrefetchHandle> + MakePrefetchFromBrowserContext( const GURL& url, std::optional<net::HttpNoVarySearchData> no_vary_search_data, const net::HttpRequestHeaders& additional_headers,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 5a6d554..a424de715 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -16505,9 +16505,9 @@ ReceivedDelegatedCapability(message.delegated_capability); // This is always called from either another renderer (through RemoteFrame) or - // from the embedder itself. As such, we nullify the parent task ID here, to + // from the embedder itself. As such, we nullify the task state ID here, to // prevent this information from leaking between renderers. - message.parent_task_id = std::nullopt; + message.task_state_id = std::nullopt; GetAssociatedLocalFrame()->PostMessageEvent( source_token, source_origin, target_origin, std::move(message));
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc index 20a28aa..20bfd64 100644 --- a/content/browser/service_worker/service_worker_container_host.cc +++ b/content/browser/service_worker/service_worker_container_host.cc
@@ -1210,8 +1210,8 @@ } // As we don't track tasks between workers and renderers, we can nullify the - // message's parent task ID. - message.parent_task_id = std::nullopt; + // message's task state ID. + message.task_state_id = std::nullopt; worker->RunAfterStartWorker( ServiceWorkerMetrics::EventType::MESSAGE,
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 32f3bf2..56136ec 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -843,8 +843,8 @@ std::move(result_callback)); // As we don't track tasks between workers and renderers, we can nullify the - // message's parent task ID. - message.parent_task_id = std::nullopt; + // message's task state ID. + message.task_state_id = std::nullopt; // TODO(crbug.com/40820909): Don't post task to the UI thread. Instead, // make all call sites run on the UI thread.
diff --git a/content/browser/service_worker/service_worker_object_host.cc b/content/browser/service_worker/service_worker_object_host.cc index 836c424..5fa22d0 100644 --- a/content/browser/service_worker/service_worker_object_host.cc +++ b/content/browser/service_worker/service_worker_object_host.cc
@@ -93,8 +93,8 @@ url::Origin::Create(container_host_->url_for_access_check())); // As we don't track tasks between workers and renderers, we can nullify the - // message's parent task ID. - message.parent_task_id = std::nullopt; + // message's task state ID. + message.task_state_id = std::nullopt; container_host_->DispatchExtendableMessageEvent(version_, std::move(message), std::move(callback));
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 706c95d4..abca3099 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -1839,8 +1839,8 @@ return; } // As we don't track tasks between workers and renderers, we can nullify the - // message's parent task ID. - message.parent_task_id = std::nullopt; + // message's task state ID. + message.task_state_id = std::nullopt; service_worker_client->container_host()->PostMessageToClient( *this, std::move(message)); }
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 7af2ba7..9217d9fee 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -606,6 +606,7 @@ "//third_party/blink/public/common:common_java", "//third_party/blink/public/mojom:android_mojo_bindings_java", "//third_party/blink/public/mojom:mojom_platform_java", + "//third_party/google-truth:google_truth_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", "//third_party/mockito:mockito_java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java index 8cb65267..75c2439 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -1745,6 +1745,10 @@ WebContentsAccessibilityImplJni.get() .moveAccessibilityFocus(mNativeObj, mAccessibilityFocusId, newAccessibilityFocusId); + // Some properties like text formatting spans are populated depending on accessibility + // focus, so we clear the cache to have them repopulated. + clearNodeInfoCacheForGivenId(newAccessibilityFocusId); + mAccessibilityFocusId = newAccessibilityFocusId; // Used to store the node (edit text field) that has input focus but not a11y focus. // Usually while the user is typing in an edit text field, a11y is on the IME and input @@ -1775,9 +1779,15 @@ return true; } + /** Gets the ID of the current accessibility focused node. */ + @CalledByNative + private int getAccessibilityFocusId() { + return mAccessibilityFocusId; + } + /** - * Send a WINDOW_CONTENT_CHANGED event after a short delay. This helps throttle such - * events from firing too quickly during animations, for example. + * Send a WINDOW_CONTENT_CHANGED event after a short delay. This helps throttle such events from + * firing too quickly during animations, for example. */ @CalledByNative private void sendDelayedWindowContentChangedEvent() {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java index 9fd1e64a..8e998a2 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -90,16 +90,19 @@ import android.annotation.SuppressLint; import android.content.ClipData; import android.content.ClipboardManager; +import android.content.res.ColorStateList; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.os.Build; import android.os.Bundle; import android.text.InputType; +import android.text.ParcelableSpan; import android.text.Spannable; import android.text.SpannableString; import android.text.style.BackgroundColorSpan; import android.text.style.ForegroundColorSpan; +import android.text.style.LocaleSpan; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; import android.text.style.SubscriptSpan; @@ -108,11 +111,14 @@ import android.text.style.TextAppearanceSpan; import android.text.style.TypefaceSpan; import android.text.style.UnderlineSpan; +import android.view.View; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import androidx.test.filters.LargeTest; import androidx.test.filters.SmallTest; +import com.google.common.truth.Expect; + import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Rule; @@ -138,9 +144,14 @@ import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.test.util.DeviceRestriction; -import java.util.HashMap; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -198,13 +209,15 @@ public AccessibilityContentShellActivityTestRule mActivityTestRule = new AccessibilityContentShellActivityTestRule(); + @Rule public final Expect expect = Expect.create(); + /** * Helper methods for setup of a basic web contents accessibility unit test. * - * These methods replace the usual setUp() method annotated with @Before because we wish to + * <p>These methods replace the usual setUp() method annotated with @Before because we wish to * load different data with each test, but the process is the same for all tests. * - * Leaving a commented @Before annotation on each method as a reminder/context clue. + * <p>Leaving a commented @Before annotation on each method as a reminder/context clue. */ /* @Before */ protected void setupTestWithHTML(String html) { @@ -1706,7 +1719,7 @@ */ @Test @SmallTest - public void testNodeInfo_spellingError() { + public void testNodeInfo_spellingError() throws Throwable { setupTestWithHTML("<input type='text' value='one wordd has an error'>"); // Call a test API to explicitly add a spelling error in the same format as @@ -1719,6 +1732,9 @@ }); mActivityTestRule.mWcax.clearNodeInfoCacheForGivenId(textNodeVirtualViewId); + // Focus on the node so the suggestions get populated. + focusNode(textNodeVirtualViewId); + // Get |AccessibilityNodeInfo| object and confirm it is not null. mNodeInfo = createAccessibilityNodeInfo(textNodeVirtualViewId); Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo); @@ -2771,232 +2787,401 @@ // ------------------ Misc tests that cannot be done as tree/event tests ------------------ // + /** Container class to hold a span and its range over a spannable text. */ + private static class SpanRange { + // Placeholder value for the end of a range. + // This should be replaced with the actual text's length before using. + public static final int UNSPECIFIED_RANGE = -1; + + public final ParcelableSpan span; + public final int start; + public int end; + + public SpanRange(ParcelableSpan span) { + this(span, 0, UNSPECIFIED_RANGE); + } + + public SpanRange(ParcelableSpan span, int start, int end) { + this.span = span; + this.start = start; + this.end = end; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(getClass().getSimpleName()); + sb.append("{"); + sb.append("from="); + sb.append(start); + sb.append(", to="); + sb.append(end); + sb.append(", span="); + if (span != null) { + sb.append(span.toString()); + } else { + sb.append("null"); + } + sb.append("}"); + return sb.toString(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof SpanRange && compareSpanRanges((SpanRange) obj, this); + } + + @Override + public int hashCode() { + return Objects.hash(span, start, end); + } + } + + private static boolean compareSpanRanges(SpanRange actual, SpanRange expected) { + if (actual == null && expected == null) { + return true; + } + if (actual == null || expected == null) { + return false; + } + if (actual.start != expected.start || actual.end != expected.end) { + return false; + } + return compareSpans(actual.span, expected.span); + } + + /** Compares subclasses of ParcelableSpans using the attributes that are actually used. */ + private static boolean compareSpans(ParcelableSpan actual, ParcelableSpan expected) { + if (actual == null && expected == null) { + return true; + } + if (actual == null || expected == null) { + return false; + } + if (!expected.getClass().isInstance(actual)) { + return false; + } + + if (expected instanceof StyleSpan) { + StyleSpan actualSpan = (StyleSpan) actual; + StyleSpan expectedSpan = (StyleSpan) expected; + return actualSpan.getStyle() == expectedSpan.getStyle(); + } + for (Class<?> cls : + List.of( + UnderlineSpan.class, + StrikethroughSpan.class, + SubscriptSpan.class, + SuperscriptSpan.class)) { + if (cls.isInstance(expected)) { + return true; + } + } + if (expected instanceof TypefaceSpan) { + TypefaceSpan actualSpan = (TypefaceSpan) actual; + TypefaceSpan expectedSpan = (TypefaceSpan) expected; + return actualSpan.getFamily().startsWith(expectedSpan.getFamily()); + } + if (expected instanceof ForegroundColorSpan) { + ForegroundColorSpan actualSpan = (ForegroundColorSpan) actual; + ForegroundColorSpan expectedSpan = (ForegroundColorSpan) expected; + return actualSpan.getForegroundColor() == expectedSpan.getForegroundColor(); + } + if (expected instanceof BackgroundColorSpan) { + BackgroundColorSpan actualSpan = (BackgroundColorSpan) actual; + BackgroundColorSpan expectedSpan = (BackgroundColorSpan) expected; + return actualSpan.getBackgroundColor() == expectedSpan.getBackgroundColor(); + } + if (expected instanceof TextAppearanceSpan) { + TextAppearanceSpan actualSpan = (TextAppearanceSpan) actual; + TextAppearanceSpan expectedSpan = (TextAppearanceSpan) expected; + return actualSpan.getTextSize() == expectedSpan.getTextSize(); + } + if (expected instanceof LocaleSpan) { + LocaleSpan actualSpan = (LocaleSpan) actual; + LocaleSpan expectedSpan = (LocaleSpan) expected; + return actualSpan.getLocale().equals(expectedSpan.getLocale()); + } + + return actual.equals(expected); + } + + private static <T> void addSpansToList( + List<SpanRange> spanRanges, SpannableString spannableString, Class<T> spanClass) { + Arrays.asList(spannableString.getSpans(0, spannableString.length(), spanClass)) + .forEach( + (span) -> { + spanRanges.add( + new SpanRange( + (ParcelableSpan) span, + spannableString.getSpanStart(span), + spannableString.getSpanEnd(span))); + }); + } + + private static TextAppearanceSpan createTextAppearanceSpanWithSize(int size) { + return new TextAppearanceSpan( + null, 0, size, ColorStateList.valueOf(0), ColorStateList.valueOf(0)); + } + @Test @SmallTest @EnableFeatures(AccessibilityFeatures.ACCESSIBILITY_TEXT_FORMATTING) - @DisabledTest(message = "https://crbug.com/400528027") public void testAccessibilityNodeInfo_textFormatting() throws Throwable { // Build a simple web page with a variety of text formatting options. setupTestFromFile("content/test/data/android/accessibility_text_formatting_examples.html"); + String serifFont = "Noto Serif"; + String sansSerifFont = "Roboto"; + String monospaceFont = "Droid Sans Mono"; + // Define test cases - Map<String, Map<SpanType, Object>> testCases = new HashMap<>(); - testCases.put("Example Text 1 - Serif Font", Map.of(SpanType.TYPEFACE_SPAN, "Noto Serif")); - testCases.put("Example Text 2 - Sans-Serif Font", Map.of(SpanType.TYPEFACE_SPAN, "Roboto")); + Map<String, List<SpanRange>> testCases = new LinkedHashMap<>(); testCases.put( - "Example Text 3 - Monospace Font", - Map.of(SpanType.TYPEFACE_SPAN, "Droid Sans Mono")); - - testCases.put("Example Text 4 - Small Font Size", Map.of(SpanType.TEXTAPPEARANCE_SPAN, 12)); - testCases.put("Example Text 5 - Large Font Size", Map.of(SpanType.TEXTAPPEARANCE_SPAN, 24)); + "Example Text - Serif Font", List.of(new SpanRange(new TypefaceSpan(serifFont)))); testCases.put( - "Example Text 6 - Font Size in Pixels", Map.of(SpanType.TEXTAPPEARANCE_SPAN, 20)); + "Example Text - Sans-Serif Font", + List.of(new SpanRange(new TypefaceSpan(sansSerifFont)))); + testCases.put( + "Example Text - Monospace Font", + List.of(new SpanRange(new TypefaceSpan(monospaceFont)))); testCases.put( - "Example Text 7 - Red Text Color", - Map.of(SpanType.FOREGROUNDCOLOR_SPAN, 0xFFFF0000)); + "Example Text - Small Font Size", + List.of(new SpanRange(createTextAppearanceSpanWithSize(13)))); testCases.put( - "Example Text 8 - Hex Code Text Color", - Map.of(SpanType.FOREGROUNDCOLOR_SPAN, 0xFF008000)); + "Example Text - Large Font Size", + List.of(new SpanRange(createTextAppearanceSpanWithSize(24)))); testCases.put( - "Example Text 9 - RGBA Text Color", - Map.of(SpanType.FOREGROUNDCOLOR_SPAN, 0xB30000FF)); + "Example Text - Font Size in Pixels", + List.of(new SpanRange(createTextAppearanceSpanWithSize(20)))); testCases.put( - "Example Text 10 - Yellow Background Color", - Map.of(SpanType.BACKGROUNDCOLOR_SPAN, 0xFFFFFF00)); + "Example Text - Red Text Color", + List.of(new SpanRange(new ForegroundColorSpan(0xFFFF0000)))); testCases.put( - "Example Text 11 - Yellow Background Color (Hex)", - Map.of(SpanType.BACKGROUNDCOLOR_SPAN, 0xFFFFFF00)); - - testCases.put("Example Text 12 - Bold Text", Map.of(SpanType.STYLE_SPAN, Typeface.BOLD)); + "Example Text - Hex Code Text Color", + List.of(new SpanRange(new ForegroundColorSpan(0xFF008000)))); testCases.put( - "Example Text 13 - Italic Text", Map.of(SpanType.STYLE_SPAN, Typeface.ITALIC)); - - testCases.put("Example Text 14 - Underlined Text", Map.of(SpanType.UNDERLINE_SPAN, true)); - testCases.put( - "Example Text 15 - Strikethrough Text", Map.of(SpanType.STRIKETHROUGH_SPAN, true)); - testCases.put("Superscripted Text", Map.of(SpanType.SUPERSCRIPT_SPAN, true)); - testCases.put("Subscripted Text", Map.of(SpanType.SUBSCRIPT_SPAN, true)); + "Example Text - RGBA Text Color", + // Expect the final blended color. + List.of(new SpanRange(new ForegroundColorSpan(0xFF0000E8)))); testCases.put( - "Example Text 18 - Bold and Italic", - Map.of(SpanType.STYLE_SPAN, Typeface.BOLD_ITALIC)); + "Example Text - Yellow Background Color", + List.of(new SpanRange(new BackgroundColorSpan(0xFFFFFF00)))); testCases.put( - "Example Text 19 - Underline and Strikethrough", - Map.of(SpanType.UNDERLINE_SPAN, true, SpanType.STRIKETHROUGH_SPAN, true)); - testCases.put( - "Example Text 20 - Red and Bold", - Map.of( - SpanType.FOREGROUNDCOLOR_SPAN, - 0xFFFF0000, - SpanType.STYLE_SPAN, - Typeface.BOLD)); - testCases.put( - "Example Text 21 - Sans-Serif, Large, Blue", - Map.of( - SpanType.TYPEFACE_SPAN, - "Roboto", - SpanType.FOREGROUNDCOLOR_SPAN, - 0xFF0000FF)); - testCases.put( - "Example Text 22 - Yellow Background, Bold, Italic", - Map.of( - SpanType.BACKGROUNDCOLOR_SPAN, - 0xFFFFFF00, - SpanType.STYLE_SPAN, - Typeface.BOLD_ITALIC)); - testCases.put( - "Example Text 23 - Monospace, RGBA, BG Hex, Bold", - Map.of( - SpanType.TYPEFACE_SPAN, - "Droid Sans Mono", - SpanType.FOREGROUNDCOLOR_SPAN, - 0xB30000FF, - SpanType.BACKGROUNDCOLOR_SPAN, - 0xFFFFFF00, - SpanType.STYLE_SPAN, - Typeface.BOLD)); + "Example Text - Yellow Background Color (Hex)", + List.of(new SpanRange(new BackgroundColorSpan(0xFFFFFF00)))); - // TODO(mschillaci): These test cases are currently disabled because of crbug.com/399652531. + testCases.put( + "Example Text - Bold Text", List.of(new SpanRange(new StyleSpan(Typeface.BOLD)))); + testCases.put( + "Example Text - Italic Text", + List.of(new SpanRange(new StyleSpan(Typeface.ITALIC)))); + + testCases.put( + "Example Text - Underlined Text", List.of(new SpanRange(new UnderlineSpan()))); + testCases.put( + "Example Text - Strikethrough Text", + List.of(new SpanRange(new StrikethroughSpan()))); + testCases.put("Superscripted Text", List.of(new SpanRange(new SuperscriptSpan()))); + testCases.put("Subscripted Text", List.of(new SpanRange(new SubscriptSpan()))); + // TODO: aluh - Super/Sub-scripted nodes are not being merged yet. // testCases.put( - // "Example Text 24 - Monospace Font inside a contenteditable", - // Map.of(SpanType.TYPEFACE_SPAN, "Droid Sans Mono")); + // "Example Text - Superscripted Text", + // List.of(new SpanRange(new SuperscriptSpan(), 15, 33))); // testCases.put( - // "Example Text 25 - Bold Text inside a contenteditable", - // Map.of(SpanType.STYLE_SPAN, Typeface.BOLD)); + // "Example Text - Subscripted Text", + // List.of(new SpanRange(new SuperscriptSpan(), 15, 31))); + + testCases.put( + "Example Text - Bold and Italic", + List.of( + new SpanRange(new StyleSpan(Typeface.BOLD)), + new SpanRange(new StyleSpan(Typeface.ITALIC)))); + testCases.put( + "Example Text - Underline and Strikethrough", + List.of( + new SpanRange(new UnderlineSpan()), + new SpanRange(new StrikethroughSpan()))); + testCases.put( + "Example Text - Red and Bold", + List.of( + new SpanRange(new ForegroundColorSpan(0xFFFF0000)), + new SpanRange(new StyleSpan(Typeface.BOLD)))); + testCases.put( + "Example Text - Sans-Serif, Large, Blue", + List.of( + new SpanRange(new TypefaceSpan(sansSerifFont)), + new SpanRange(new ForegroundColorSpan(0xFF0000FF)))); + testCases.put( + "Example Text - Yellow Background, Bold, Italic", + List.of( + new SpanRange(new BackgroundColorSpan(0xFFFFFF00)), + new SpanRange(new StyleSpan(Typeface.BOLD)), + new SpanRange(new StyleSpan(Typeface.ITALIC)))); + testCases.put( + "Example Text - Monospace, RGBA, BG Hex, Bold", + List.of( + new SpanRange(new TypefaceSpan(monospaceFont)), + new SpanRange(new ForegroundColorSpan(0xFF0000E8)), + new SpanRange(new BackgroundColorSpan(0xFFFFFF00)), + new SpanRange(new StyleSpan(Typeface.BOLD)))); + // TODO: aluh - URL nodes are not being merged yet. // testCases.put( - // "Example Text 26 - Small red superscript inside content editable", - // Map.of(SpanType.FOREGROUNDCOLOR_SPAN, 0xFFFF0000, SpanType.SUPERSCRIPT_SPAN, true)); - // testCases.put( - // "Example Text 27 - Large bold italic strikethrough underlined serif in - // contenteditable", - // Map.of(SpanType.TYPEFACE_SPAN, "Noto Serif", - // SpanType.UNDERLINE_SPAN, true, SpanType.STRIKETHROUGH_SPAN, true, - // SpanType.STYLE_SPAN, Typeface.BOLD_ITALIC, - // SpanType.TEXTAPPEARANCE_SPAN, 24)); + // "Example Text - An example link", + // List.of(new SpanRange(new URLSpan("https://www.example.com/"), 18, 25))); + testCases.put( + "Example Text - Nested bolded text", + List.of(new SpanRange(new StyleSpan(Typeface.BOLD), 22, 28))); + testCases.put( + "Example Text - Overlapping text styling", + List.of( + new SpanRange(new StyleSpan(Typeface.ITALIC), 15, 27), + new SpanRange(new StyleSpan(Typeface.BOLD), 27, 31), + new SpanRange(new StyleSpan(Typeface.ITALIC), 27, 31), + new SpanRange(new StyleSpan(Typeface.ITALIC), 31, 39))); + testCases.put( + "Example Text - Same style multiple times", + List.of( + new SpanRange(new StyleSpan(Typeface.ITALIC), 15, 19), + new SpanRange(new StyleSpan(Typeface.ITALIC), 26, 34))); + testCases.put( + "Example Text - Consecutive same style not merged", + List.of( + new SpanRange(new StyleSpan(Typeface.ITALIC), 27, 31), + new SpanRange(new StyleSpan(Typeface.ITALIC), 31, 37))); + testCases.put( + "Example Text - Mixed italic, underline, and strikethrough styles", + List.of( + new SpanRange(new StyleSpan(Typeface.ITALIC), 21, 29), + new SpanRange(new StyleSpan(Typeface.ITALIC), 29, 44), + new SpanRange(new StyleSpan(Typeface.ITALIC), 44, 57), + new SpanRange(new UnderlineSpan(), 29, 44), + new SpanRange(new UnderlineSpan(), 44, 57), + new SpanRange(new StrikethroughSpan(), 44, 57))); + testCases.put( + "Example Text - Nested monospace font text", + List.of(new SpanRange(new TypefaceSpan(monospaceFont), 22, 36))); + testCases.put( + "Example Text - Nested pixel font size text", + List.of(new SpanRange(createTextAppearanceSpanWithSize(20), 22, 37))); + testCases.put( + "Example Text - Nested red color text", + List.of(new SpanRange(new ForegroundColorSpan(0xFFFF0000), 22, 31))); + testCases.put( + "Example Text - Nested yellow background color text", + List.of(new SpanRange(new BackgroundColorSpan(0xFFFFFF00), 22, 45))); + + testCases.put( + "Example Text - Nested 繁體中文 text", + List.of(new SpanRange(new LocaleSpan(Locale.TRADITIONAL_CHINESE), 22, 26))); + + // TODO: crbug.com/421462039 - Update wrong background color span after fix. + testCases.put( + "Example Text - Nested foreground and background colors with font sizes and styles", + List.of( + new SpanRange(new ForegroundColorSpan(0xFF000000), 0, 22), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 22, 37), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 37, 48), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 48, 55), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 55, 59), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 59, 64), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 64, 65), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 65, 70), + new SpanRange(new ForegroundColorSpan(0xFFFF0000), 70, 81), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 0, 22), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 22, 37), + new SpanRange(new BackgroundColorSpan(0xFFFFFF00), 37, 48), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 48, 55), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 55, 59), + new SpanRange(new BackgroundColorSpan(0xFFFFFF00), 59, 64), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 64, 65), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 65, 70), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 70, 81), + new SpanRange(createTextAppearanceSpanWithSize(16), 0, 22), + new SpanRange(createTextAppearanceSpanWithSize(16), 22, 37), + new SpanRange(createTextAppearanceSpanWithSize(16), 37, 48), + new SpanRange(createTextAppearanceSpanWithSize(16), 48, 55), + new SpanRange(createTextAppearanceSpanWithSize(20), 55, 59), + new SpanRange(createTextAppearanceSpanWithSize(16), 59, 64), + new SpanRange(createTextAppearanceSpanWithSize(16), 64, 65), + new SpanRange(createTextAppearanceSpanWithSize(16), 65, 70), + new SpanRange(createTextAppearanceSpanWithSize(16), 70, 81), + new SpanRange(new StyleSpan(Typeface.ITALIC), 48, 55), + new SpanRange(new StyleSpan(Typeface.ITALIC), 55, 59), + new SpanRange(new StyleSpan(Typeface.BOLD), 65, 70))); + + // TODO: crbug.com/421462039 - Update wrong background color span after fix. + testCases.put( + "Example Text - Some background color and italic text", + List.of( + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 0, 20), + new SpanRange(new BackgroundColorSpan(0xFFFFFF00), 20, 41), + new SpanRange(new BackgroundColorSpan(0xFFFFFFFF), 41, 47), + new SpanRange(new BackgroundColorSpan(0xFFFFFF00), 47, 52), + new SpanRange(new StyleSpan(Typeface.ITALIC), 41, 47))); + + // TODO: crbug.com/426007976 - Add back missing span once zero font size nodes are fixed. + testCases.put( + "Example Text - Nested invisible text", + List.of( + new SpanRange(createTextAppearanceSpanWithSize(16), 0, 22), + // new SpanRange(createTextAppearanceSpanWithSize(0), 22, 31), + new SpanRange(createTextAppearanceSpanWithSize(16), 31, 36))); + + // TODO: crbug.com/399652531 - Add contenteditable test cases. // Iterate over test cases - for (Entry<String, Map<SpanType, Object>> entry : testCases.entrySet()) { + for (Entry<String, List<SpanRange>> entry : testCases.entrySet()) { String testString = entry.getKey(); - Map<SpanType, Object> expectedSpans = entry.getValue(); + List<SpanRange> expectedSpans = entry.getValue(); + expectedSpans.forEach( + (spanRange) -> { + if (spanRange != null && spanRange.end == SpanRange.UNSPECIFIED_RANGE) { + spanRange.end = testString.length(); + } + }); // Find node matching test string for this test case int vvid = waitForNodeMatching(sTextMatcher, testString); + expect.withMessage("Could not find node for: " + testString) + .that(vvid) + .isNotEqualTo(View.NO_ID); + if (vvid == View.NO_ID) { + // Don't stop other test cases. + continue; + } + focusNode(vvid); mNodeInfo = createAccessibilityNodeInfo(vvid); - Assert.assertNotNull("Could not find node for: " + testString, mNodeInfo); + expect.withMessage("Could not create ANI for: " + testString) + .that(mNodeInfo) + .isNotNull(); + if (mNodeInfo == null) { + // Don't stop other test cases. + continue; + } SpannableString spannableUnderTest = new SpannableString(mNodeInfo.getText()); - // For each of the expected Spannables in our expectations, check they are present. - for (Entry<SpanType, Object> spanType : expectedSpans.entrySet()) { - SpanType expectedSpanType = spanType.getKey(); - Object value = spanType.getValue(); + // Get all the spans we care about. + List<SpanRange> actualSpans = new LinkedList<>(); + addSpansToList(actualSpans, spannableUnderTest, StyleSpan.class); + addSpansToList(actualSpans, spannableUnderTest, UnderlineSpan.class); + addSpansToList(actualSpans, spannableUnderTest, StrikethroughSpan.class); + addSpansToList(actualSpans, spannableUnderTest, SubscriptSpan.class); + addSpansToList(actualSpans, spannableUnderTest, SuperscriptSpan.class); + addSpansToList(actualSpans, spannableUnderTest, TypefaceSpan.class); + addSpansToList(actualSpans, spannableUnderTest, ForegroundColorSpan.class); + addSpansToList(actualSpans, spannableUnderTest, BackgroundColorSpan.class); + addSpansToList(actualSpans, spannableUnderTest, TextAppearanceSpan.class); + addSpansToList(actualSpans, spannableUnderTest, LocaleSpan.class); - // Switch over the SpanType and perform each type of check separately. - switch (expectedSpanType) { - case STYLE_SPAN -> { - StyleSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), StyleSpan.class); - Assert.assertEquals( - "Incorrect number of StyleSpan's on text: " + testString, - 1, - spans.length); - Assert.assertEquals( - "Did not find correct StyleSpan value on: " + testString, - (int) value, - spans[0].getStyle()); - } - case UNDERLINE_SPAN -> { - UnderlineSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), UnderlineSpan.class); - Assert.assertEquals( - "Incorrect number of UnderlineSpan's on text: " + testString, - 1, - spans.length); - } - case STRIKETHROUGH_SPAN -> { - StrikethroughSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), StrikethroughSpan.class); - Assert.assertEquals( - "Incorrect number of StrikethroughSpan's on text: " + testString, - 1, - spans.length); - } - case SUBSCRIPT_SPAN -> { - SubscriptSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), SubscriptSpan.class); - Assert.assertEquals( - "Incorrect number of SubscriptSpan's on text: " + testString, - 1, - spans.length); - } - case SUPERSCRIPT_SPAN -> { - SuperscriptSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), SuperscriptSpan.class); - Assert.assertEquals( - "Incorrect number of SuperscriptSpan's on text: " + testString, - 1, - spans.length); - } - case TYPEFACE_SPAN -> { - TypefaceSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), TypefaceSpan.class); - Assert.assertEquals( - "Incorrect number of TypefaceSpan's on text: " + testString, - 1, - spans.length); - Assert.assertEquals( - "Did not find correct TypefaceSpan value on: " + testString, - (String) value, - spans[0].getFamily()); - } - case FOREGROUNDCOLOR_SPAN -> { - ForegroundColorSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), ForegroundColorSpan.class); - Assert.assertEquals( - "Incorrect number of ForegroundColorSpan's on text: " + testString, - 1, - spans.length); - Assert.assertEquals( - "Did not find correct ForegroundColorSpan value on: " + testString, - (int) value, - spans[0].getForegroundColor()); - } - case BACKGROUNDCOLOR_SPAN -> { - BackgroundColorSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), BackgroundColorSpan.class); - Assert.assertEquals( - "Incorrect number of BackgroundColorSpan's on text: " + testString, - 1, - spans.length); - Assert.assertEquals( - "Did not find correct BackgroundColorSpan value on: " + testString, - (int) value, - spans[0].getBackgroundColor()); - } - case TEXTAPPEARANCE_SPAN -> { - TextAppearanceSpan[] spans = - spannableUnderTest.getSpans( - 0, spannableUnderTest.length(), TextAppearanceSpan.class); - Assert.assertEquals( - "Incorrect number of TextAppearanceSpan's on text: " + testString, - 1, - spans.length); - Assert.assertEquals( - "Did not find correct TextAppearanceSpan value on: " + testString, - (int) value, - spans[0].getTextSize()); - } - } - } + expect.withMessage("Verify spans on text: " + testString) + .that(actualSpans) + .containsAtLeastElementsIn(expectedSpans); + expect.withMessage("Duplicate spans on text: " + testString) + .that(actualSpans) + .containsNoDuplicates(); } } @@ -3049,17 +3234,4 @@ mActivityTestRule.mWcax.forceRecordUMAHistogramsForTesting(); mActivityTestRule.mWcax.forceRecordCacheUMAHistogramsForTesting(); } - - // Helper enum for mapping values to reduce boilerplate code. - enum SpanType { - STYLE_SPAN, - UNDERLINE_SPAN, - STRIKETHROUGH_SPAN, - SUBSCRIPT_SPAN, - SUPERSCRIPT_SPAN, - TYPEFACE_SPAN, - FOREGROUNDCOLOR_SPAN, - BACKGROUNDCOLOR_SPAN, - TEXTAPPEARANCE_SPAN - } }
diff --git a/content/test/data/android/accessibility_text_formatting_examples.html b/content/test/data/android/accessibility_text_formatting_examples.html index 36253502..f92e96bb 100644 --- a/content/test/data/android/accessibility_text_formatting_examples.html +++ b/content/test/data/android/accessibility_text_formatting_examples.html
@@ -25,6 +25,10 @@ font-size: 20px; } + .font-size-zero { + font-size: 0px; + } + .color-red { color: red; } @@ -65,7 +69,7 @@ text-decoration: line-through; } - .strikethrough_underlined { + .strikethrough-underlined { text-decoration: line-through underline; } @@ -82,42 +86,64 @@ </head> <body> - <p class="font-serif">Example Text 1 - Serif Font</p> - <p class="font-sans-serif">Example Text 2 - Sans-Serif Font</p> - <p class="font-monospace">Example Text 3 - Monospace Font</p> + <p class="font-serif">Example Text - Serif Font</p> + <p class="font-sans-serif">Example Text - Sans-Serif Font</p> + <p class="font-monospace">Example Text - Monospace Font</p> - <p class="font-size-small">Example Text 4 - Small Font Size</p> - <p class="font-size-large">Example Text 5 - Large Font Size</p> - <p class="font-size-pixels">Example Text 6 - Font Size in Pixels</p> + <p class="font-size-small">Example Text - Small Font Size</p> + <p class="font-size-large">Example Text - Large Font Size</p> + <p class="font-size-pixels">Example Text - Font Size in Pixels</p> - <p class="color-red">Example Text 7 - Red Text Color</p> - <p class="color-hex">Example Text 8 - Hex Code Text Color</p> - <p class="color-rgba">Example Text 9 - RGBA Text Color</p> + <p class="color-red">Example Text - Red Text Color</p> + <p class="color-hex">Example Text - Hex Code Text Color</p> + <p class="color-rgba">Example Text - RGBA Text Color</p> - <p class="bg-color-yellow">Example Text 10 - Yellow Background Color</p> - <p class="bg-color-hex">Example Text 11 - Yellow Background Color (Hex)</p> + <p class="bg-color-yellow">Example Text - Yellow Background Color</p> + <p class="bg-color-hex">Example Text - Yellow Background Color (Hex)</p> - <p class="bold">Example Text 12 - Bold Text</p> - <p class="italic">Example Text 13 - Italic Text</p> - <p class="underline">Example Text 14 - Underlined Text</p> - <p class="strikethrough">Example Text 15 - Strikethrough Text</p> + <p class="bold">Example Text - Bold Text</p> + <p class="italic">Example Text - Italic Text</p> + <p class="underline">Example Text - Underlined Text</p> + <p class="strikethrough">Example Text - Strikethrough Text</p> - <p>Example Text 16 - Superscript: Normal Text<sup class="superscript">Superscripted Text</sup></p> - <p>Example Text 17 - Subscript: Normal Text<sub class="subscript">Subscripted Text</sub></p> + <p>Example Text - <sup class="superscript">Superscripted Text</sup></p> + <p>Example Text - <sub class="subscript">Subscripted Text</sub></p> - <p class="bold italic">Example Text 18 - Bold and Italic</p> - <p class="strikethrough_underlined">Example Text 19 - Underline and Strikethrough</p> - <p class="color-red bold">Example Text 20 - Red and Bold</p> - <p class="font-sans-serif font-size-large color-blue">Example Text 21 - Sans-Serif, Large, Blue</p> - <p class="bg-color-yellow bold italic">Example Text 22 - Yellow Background, Bold, Italic</p> - <p class="font-monospace color-rgba bg-color-hex bold">Example Text 23 - Monospace, RGBA, BG Hex, Bold</p> + <p class="bold italic">Example Text - Bold and Italic</p> + <p class="strikethrough-underlined">Example Text - Underline and Strikethrough</p> + <p class="color-red bold">Example Text - Red and Bold</p> + <p class="font-sans-serif font-size-large color-blue">Example Text - Sans-Serif, Large, Blue</p> + <p class="bg-color-yellow bold italic">Example Text - Yellow Background, Bold, Italic</p> + <p class="font-monospace color-rgba bg-color-hex bold">Example Text - Monospace, RGBA, BG Hex, Bold</p> + + <p>Example Text - An <a href="https://www.example.com/">example</a> link</p> + + <p>Example Text - Nested <span class="bold">bolded</span> text</p> + <p>Example Text - <span class="italic">Overlapping <span class="bold">text</span> styling</span></p> + <p>Example Text - <span class="italic">Same</span> style <span class="italic">multiple</span> times</p> + <p>Example Text - Consecutive <span class="italic">same</span><span class="italic"> style</span> not merged</p> + <p>Example Text - Mixed <span class="italic">italic, <span class="underline">underline, and <span class="strikethrough-underlined">strikethrough</span></span></span> styles</p> + + <p>Example Text - Nested <span class="font-monospace">monospace font</span> text</p> + <p>Example Text - Nested <span class="font-size-pixels">pixel font size</span> text</p> + <p>Example Text - Nested <span class="color-red">red color</span> text</p> + <p>Example Text - Nested <span class="bg-color-yellow">yellow background color</span> text</p> + + <p>Example Text - Nested <span lang="zh-TW">繁體中文</span> text</p> + + <p>Example Text - Nested <span class="color-red">foreground and <span class="bg-color-yellow">background <span class="italic">colors <span class="font-size-pixels">with</span></span> font</span> <span class="bold">sizes</span> and styles</span></p> + <p>Example Text - Some <span style="background-color: yellow;">background color and <span style="font-style: italic;">italic</span> text</span></p> + + <p>Example Text - Empty <span class="bold"></span>style text</p> + <p>Example Text - Empty <a href="https://www.example.com/"></a>link text</p> + <p>Example Text - Nested <span class="font-size-zero">invisible</span> text</p> <div class="contenteditable-test" contenteditable="true"> - <p class="font-monospace">Example Text 24 - Monospace Font inside a contenteditable</p> - <p class="bold">Example Text 25 - Bold Text inside a contenteditable</p> - <p class="color-red"><sup class="superscript">Example Text 26 - Small red superscript inside content editable</sup></p> - <p class="font-serif strikethrough_underlined bold italic font-size-large">Example Text 27 - Large bold italic strikethrough underlined serif in contenteditable</p> + <p class="font-monospace">Example ContentEditable - Monospace Font inside a contenteditable</p> + <p class="bold">Example ContentEditable - Bold Text inside a contenteditable</p> + <p class="color-red"><sup class="superscript">Example ContentEditable - Small red superscript inside content editable</sup></p> + <p class="font-serif strikethrough-underlined bold italic font-size-large">Example ContentEditable - Large bold italic strikethrough underlined serif in contenteditable</p> </div> </body> -</html> \ No newline at end of file +</html>
diff --git "a/infra/config/generated/builders/ci/GPU Mac Builder \050dbg\051/targets/chromium.gpu.json" "b/infra/config/generated/builders/ci/GPU Mac Builder \050dbg\051/targets/chromium.gpu.json" index a21180ba..04253cd6 100644 --- "a/infra/config/generated/builders/ci/GPU Mac Builder \050dbg\051/targets/chromium.gpu.json" +++ "b/infra/config/generated/builders/ci/GPU Mac Builder \050dbg\051/targets/chromium.gpu.json"
@@ -783,7 +783,8 @@ "hard_timeout": 1800, "idempotent": false, "io_timeout": 1800, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "telemetry_gpu_integration_test", "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
diff --git "a/infra/config/generated/builders/ci/Mac Retina Debug \050AMD\051/targets/chromium.gpu.json" "b/infra/config/generated/builders/ci/Mac Retina Debug \050AMD\051/targets/chromium.gpu.json" index 194cd68..2340b0c 100644 --- "a/infra/config/generated/builders/ci/Mac Retina Debug \050AMD\051/targets/chromium.gpu.json" +++ "b/infra/config/generated/builders/ci/Mac Retina Debug \050AMD\051/targets/chromium.gpu.json"
@@ -339,7 +339,8 @@ "hard_timeout": 1800, "idempotent": false, "io_timeout": 1800, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "telemetry_gpu_integration_test", "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
diff --git a/infra/config/generated/builders/try/gpu-try-mac-amd-retina-dbg/targets/chromium.gpu.json b/infra/config/generated/builders/try/gpu-try-mac-amd-retina-dbg/targets/chromium.gpu.json index 1c8b108..1711caa0 100644 --- a/infra/config/generated/builders/try/gpu-try-mac-amd-retina-dbg/targets/chromium.gpu.json +++ b/infra/config/generated/builders/try/gpu-try-mac-amd-retina-dbg/targets/chromium.gpu.json
@@ -340,7 +340,8 @@ "hard_timeout": 1800, "idempotent": false, "io_timeout": 1800, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "telemetry_gpu_integration_test", "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.star b/infra/config/subprojects/chromium/ci/chromium.gpu.star index 5c1c5e66..30e8da0 100644 --- a/infra/config/subprojects/chromium/ci/chromium.gpu.star +++ b/infra/config/subprojects/chromium/ci/chromium.gpu.star
@@ -571,6 +571,13 @@ "puppet_production", ], per_test_modifications = { + "pixel_skia_gold_metal_passthrough_graphite_test": targets.per_test_modification( + mixins = targets.mixin( + swarming = targets.swarming( + shards = 2, + ), + ), + ), "tab_capture_end2end_tests": targets.remove( reason = "Run these only on Release bots.", ),
diff --git a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm index 073fce8..b42d70b 100644 --- a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm
@@ -1208,7 +1208,8 @@ LoadAndFillCreditCardForm(); __block bool save_card_bottomsheet_shown = false; - OCMStub([autofill_commands_handler_ showSaveCardBottomSheet]) + OCMStub([autofill_commands_handler_ + showSaveCardBottomSheetOnOriginWebState:web_state()]) .andDo(^(NSInvocation* invocation) { save_card_bottomsheet_shown = true; }); @@ -1259,7 +1260,8 @@ LoadAndFillCreditCardForm(); __block bool save_card_bottomsheet_shown = false; - OCMStub([autofill_commands_handler_ showSaveCardBottomSheet]) + OCMStub([autofill_commands_handler_ + showSaveCardBottomSheetOnOriginWebState:web_state()]) .andDo(^(NSInvocation* invocation) { save_card_bottomsheet_shown = true; }); @@ -1343,7 +1345,8 @@ FieldPropertiesFlags::kAutofilled); __block bool save_card_bottomsheet_shown = false; - OCMStub([autofill_commands_handler_ showSaveCardBottomSheet]) + OCMStub([autofill_commands_handler_ + showSaveCardBottomSheetOnOriginWebState:web_state()]) .andDo(^(NSInvocation* invocation) { save_card_bottomsheet_shown = true; });
diff --git a/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.h b/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.h index b43c64f9..dd942da 100644 --- a/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.h +++ b/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.h
@@ -35,6 +35,7 @@ // AutofillImageFetcher: gfx::Image ResolveCardArtImage(const GURL& card_art_url, const gfx::Image& card_art_image) override; + gfx::Image ResolveValuableImage(const gfx::Image& valuable_image) override; private: std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher_;
diff --git a/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.mm b/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.mm index 03ef181..91597baf 100644 --- a/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.mm +++ b/ios/chrome/browser/autofill/model/autofill_image_fetcher_impl.mm
@@ -118,4 +118,9 @@ return gfx::Image(image); } +gfx::Image AutofillImageFetcherImpl::ResolveValuableImage( + const gfx::Image& valuable_image) { + return valuable_image; +} + } // namespace autofill
diff --git a/ios/chrome/browser/autofill/model/bottom_sheet/autofill_bottom_sheet_tab_helper.mm b/ios/chrome/browser/autofill/model/bottom_sheet/autofill_bottom_sheet_tab_helper.mm index aa731bc8..40245cfc 100644 --- a/ios/chrome/browser/autofill/model/bottom_sheet/autofill_bottom_sheet_tab_helper.mm +++ b/ios/chrome/browser/autofill/model/bottom_sheet/autofill_bottom_sheet_tab_helper.mm
@@ -131,7 +131,7 @@ void AutofillBottomSheetTabHelper::ShowSaveCardBottomSheet( std::unique_ptr<autofill::SaveCardBottomSheetModel> model) { save_card_bottom_sheet_model_ = std::move(model); - [commands_handler_ showSaveCardBottomSheet]; + [commands_handler_ showSaveCardBottomSheetOnOriginWebState:web_state_]; } void AutofillBottomSheetTabHelper::ShowVirtualCardEnrollmentBottomSheet(
diff --git a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm index 1d573963..f0fbe50 100644 --- a/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm +++ b/ios/chrome/browser/autofill/ui_bundled/ios_chrome_payments_autofill_client_unittest.mm
@@ -79,7 +79,7 @@ - (void)showPlusAddressesBottomSheet { } -- (void)showSaveCardBottomSheet { +- (void)showSaveCardBottomSheetOnOriginWebState:(web::WebState*)originWebState { _showSaveCardBottomSheet = YES; }
diff --git a/ios/chrome/browser/badges/ui_bundled/BUILD.gn b/ios/chrome/browser/badges/ui_bundled/BUILD.gn index 1c49692..e0d7ed1 100644 --- a/ios/chrome/browser/badges/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/badges/ui_bundled/BUILD.gn
@@ -56,6 +56,7 @@ ":util", "//base", "//components/autofill/core/browser", + "//components/omnibox/common", "//components/password_manager/core/common", "//ios/chrome/app/strings", "//ios/chrome/browser/fullscreen/ui_bundled:ui", @@ -68,6 +69,7 @@ "//ios/chrome/browser/overlays/model/public/common/infobars", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", + "//ios/chrome/browser/shared/model/url:constants", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/public/commands", "//ios/chrome/browser/shared/public/features",
diff --git a/ios/chrome/browser/badges/ui_bundled/badge_mediator.mm b/ios/chrome/browser/badges/ui_bundled/badge_mediator.mm index 56f0aa84..87758c8 100644 --- a/ios/chrome/browser/badges/ui_bundled/badge_mediator.mm +++ b/ios/chrome/browser/badges/ui_bundled/badge_mediator.mm
@@ -8,6 +8,7 @@ #import "base/apple/foundation_util.h" #import "base/metrics/user_metrics.h" +#import "components/omnibox/common/omnibox_features.h" #import "ios/chrome/browser/badges/ui_bundled/badge_button.h" #import "ios/chrome/browser/badges/ui_bundled/badge_consumer.h" #import "ios/chrome/browser/badges/ui_bundled/badge_item.h" @@ -27,6 +28,7 @@ #import "ios/chrome/browser/overlays/model/public/overlay_presenter.h" #import "ios/chrome/browser/overlays/model/public/overlay_presenter_observer_bridge.h" #import "ios/chrome/browser/overlays/model/public/overlay_request_queue.h" +#import "ios/chrome/browser/shared/model/url/chrome_url_constants.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h" #import "ios/chrome/browser/shared/public/commands/browser_coordinator_commands.h" @@ -79,6 +81,7 @@ @end @implementation BadgeMediator +@synthesize offTheRecordBadge = _offTheRecordBadge; - (instancetype)initWithWebStateList:(WebStateList*)webStateList overlayPresenter:(OverlayPresenter*)overlayPresenter @@ -216,6 +219,20 @@ : kBadgeTypePermissionsCamera; } +- (id<BadgeItem>)offTheRecordBadge { + if (!base::FeatureList::IsEnabled(omnibox::kOmniboxMobileParityUpdate)) { + return _offTheRecordBadge; + } + + // When Parity is enabled, don't show the incognito badge on NTP. The + // placeholder with the default search engine logo will be shown instead. + if ([self isCurrentWebStateShowingNTP]) { + return nil; + } + + return _offTheRecordBadge; +} + #pragma mark - Accessor helpers // Updates the consumer for the current active WebState. @@ -496,4 +513,13 @@ } } +- (BOOL)isCurrentWebStateShowingNTP { + if (!self.webStateList || !self.webStateList->GetActiveWebState()) { + return NO; + } + + return self.webStateList->GetActiveWebState()->GetVisibleURL() == + kChromeUINewTabURL; +} + @end
diff --git a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm index 50683ab..32aa67a 100644 --- a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm +++ b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
@@ -2071,11 +2071,17 @@ [self.plusAddressBottomSheetCoordinator start]; } -- (void)showSaveCardBottomSheet { +- (void)showSaveCardBottomSheetOnOriginWebState:(web::WebState*)originWebState { if (self.saveCardBottomSheetCoordinator) { [self.saveCardBottomSheetCoordinator stop]; } + if (self.activeWebState != originWebState) { + // Do not show the sheet if the current tab is not the one where the + // bottomsheet show request was triggered from. + return; + } + self.saveCardBottomSheetCoordinator = [[SaveCardBottomSheetCoordinator alloc] initWithBaseViewController:self.viewController browser:self.browser];
diff --git a/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm index 06ca8b09..39b2cab 100644 --- a/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm +++ b/ios/chrome/browser/collaboration/model/messaging/infobar/collaboration_group_infobar_delegate.mm
@@ -99,7 +99,6 @@ case CollaborationEvent::TAB_GROUP_REMOVED: case CollaborationEvent::UNDEFINED: case CollaborationEvent::COLLABORATION_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: use_first_available_browser = true; break; } @@ -260,8 +259,6 @@ case CollaborationEvent::COLLABORATION_ADDED: case CollaborationEvent::COLLABORATION_REMOVED: case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: - // TODO(crbug.com/422424386): Implement for versioning. return l10n_util::GetStringUTF16( IDS_IOS_COLLABORATION_GROUP_DEFAULT_PRIMARY_TOOLBAR_BUTTON); } @@ -285,8 +282,6 @@ case CollaborationEvent::COLLABORATION_ADDED: case CollaborationEvent::COLLABORATION_REMOVED: case CollaborationEvent::COLLABORATION_MEMBER_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: - // TODO(crbug.com/422424386): Implement for versioning. break; } @@ -361,8 +356,6 @@ break; case CollaborationEvent::TAB_GROUP_REMOVED: case CollaborationEvent::COLLABORATION_REMOVED: - case CollaborationEvent::VERSION_OUT_OF_DATE: - // TODO(crbug.com/422424386): Implement for versioning. symbolName = kTabGroupsSymbol; break; }
diff --git a/ios/chrome/browser/first_run/ui_bundled/BUILD.gn b/ios/chrome/browser/first_run/ui_bundled/BUILD.gn index b6c8fc8f..260d07ee 100644 --- a/ios/chrome/browser/first_run/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/first_run/ui_bundled/BUILD.gn
@@ -48,6 +48,7 @@ ":utils", "//base", "//base:i18n", + "//components/feature_engagement/public", "//components/metrics", "//components/signin/public/identity_manager", "//ios/chrome/app:tests_hook", @@ -57,6 +58,7 @@ "//ios/chrome/browser/authentication/ui_bundled/history_sync", "//ios/chrome/browser/authentication/ui_bundled/signin:constants", "//ios/chrome/browser/docking_promo/coordinator", + "//ios/chrome/browser/feature_engagement/model", "//ios/chrome/browser/first_run/model", "//ios/chrome/browser/first_run/ui_bundled/animated_lens/coordinator", "//ios/chrome/browser/first_run/ui_bundled/best_features/coordinator",
diff --git a/ios/chrome/browser/first_run/ui_bundled/first_run_coordinator.mm b/ios/chrome/browser/first_run/ui_bundled/first_run_coordinator.mm index 49b5e35..5a5079d 100644 --- a/ios/chrome/browser/first_run/ui_bundled/first_run_coordinator.mm +++ b/ios/chrome/browser/first_run/ui_bundled/first_run_coordinator.mm
@@ -11,6 +11,8 @@ #import "base/metrics/histogram_functions.h" #import "base/notreached.h" #import "base/time/time.h" +#import "components/feature_engagement/public/event_constants.h" +#import "components/feature_engagement/public/tracker.h" #import "components/metrics/metrics_service.h" #import "components/signin/public/base/signin_metrics.h" #import "ios/chrome/browser/authentication/ui_bundled/continuation.h" @@ -19,6 +21,7 @@ #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_constants.h" #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_context_style.h" #import "ios/chrome/browser/docking_promo/coordinator/docking_promo_coordinator.h" +#import "ios/chrome/browser/feature_engagement/model/tracker_factory.h" #import "ios/chrome/browser/first_run/model/first_run_metrics.h" #import "ios/chrome/browser/first_run/ui_bundled/animated_lens/coordinator/animated_lens_promo_coordinator.h" #import "ios/chrome/browser/first_run/ui_bundled/best_features/coordinator/best_features_screen_coordinator.h" @@ -143,6 +146,14 @@ // The user went through all screens of the FRE. base::UmaHistogramEnumeration(first_run::kFirstRunStageHistogram, first_run::kComplete); + + feature_engagement::Tracker* tracker = + feature_engagement::TrackerFactory::GetForProfile(self.profile); + + if (tracker) { + tracker->NotifyEvent(feature_engagement::events::kIOSFirstRunComplete); + } + WriteFirstRunSentinel(); [self.delegate didFinishFirstRun];
diff --git a/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm b/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm index df60cb4..21e7473 100644 --- a/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm +++ b/ios/chrome/browser/home_customization/coordinator/home_customization_background_picker_action_sheet_coordinator.mm
@@ -79,10 +79,9 @@ - (void)start { __weak __typeof(self) weakSelf = self; image_fetcher::ImageFetcherService* imageFetcherService = - ImageFetcherServiceFactory::GetForProfile(self.browser->GetProfile()); + ImageFetcherServiceFactory::GetForProfile(self.profile); HomeBackgroundImageService* homeBackgroundImageService = - HomeBackgroundImageServiceFactory::GetForProfile( - self.browser->GetProfile()); + HomeBackgroundImageServiceFactory::GetForProfile(self.profile); _mediator = [[HomeCustomizationBackgroundPickerActionSheetMediator alloc] init];
diff --git a/ios/chrome/browser/home_customization/model/BUILD.gn b/ios/chrome/browser/home_customization/model/BUILD.gn index f1bf865..2fe2293 100644 --- a/ios/chrome/browser/home_customization/model/BUILD.gn +++ b/ios/chrome/browser/home_customization/model/BUILD.gn
@@ -26,10 +26,12 @@ deps = [ "//base", "//components/keyed_service/core", + "//components/pref_registry", "//components/sync/protocol", "//components/themes", "//ios/chrome/browser/home_customization/utils", "//ios/chrome/browser/shared/model/application_context", + "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory", "//services/network/public/cpp",
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service.h b/ios/chrome/browser/home_customization/model/home_background_customization_service.h index de425f8..063222d 100644 --- a/ios/chrome/browser/home_customization/model/home_background_customization_service.h +++ b/ios/chrome/browser/home_customization/model/home_background_customization_service.h
@@ -15,11 +15,13 @@ class GURL; class HomeBackgroundCustomizationServiceObserver; +class PrefRegistrySimple; +class PrefService; // Service for allowing customization of the Home surface background. class HomeBackgroundCustomizationService : public KeyedService { public: - explicit HomeBackgroundCustomizationService(); + explicit HomeBackgroundCustomizationService(PrefService* pref_service); HomeBackgroundCustomizationService( const HomeBackgroundCustomizationService&) = delete; @@ -63,12 +65,24 @@ void AddObserver(HomeBackgroundCustomizationServiceObserver* observer); void RemoveObserver(HomeBackgroundCustomizationServiceObserver* observer); + // Registers the profile prefs associated with this service. + static void RegisterProfilePrefs(PrefRegistrySimple* registry); + private: // Alerts observers when the background changes. void NotifyObserversOfBackgroundChange(); + // Stores the current theme to disk. + void StoreCurrentTheme(); + + // Loads the theme data from disk. + void LoadCurrentTheme(); + sync_pb::ThemeSpecificsIos current_theme_; + // The PrefService associated with the Profile. + raw_ptr<PrefService> pref_service_; + base::ObserverList<HomeBackgroundCustomizationServiceObserver> observers_; };
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service.mm b/ios/chrome/browser/home_customization/model/home_background_customization_service.mm index cce8c086..5604dc7 100644 --- a/ios/chrome/browser/home_customization/model/home_background_customization_service.mm +++ b/ios/chrome/browser/home_customization/model/home_background_customization_service.mm
@@ -4,17 +4,32 @@ #import "ios/chrome/browser/home_customization/model/home_background_customization_service.h" +#import "base/base64.h" +#import "base/logging.h" +#import "components/prefs/pref_registry_simple.h" +#import "components/prefs/pref_service.h" #import "components/sync/protocol/theme_types.pb.h" #import "ios/chrome/browser/home_customization/model/home_background_customization_service_observer.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "third_party/skia/include/core/SkColor.h" #import "url/gurl.h" -HomeBackgroundCustomizationService::HomeBackgroundCustomizationService() {} +HomeBackgroundCustomizationService::HomeBackgroundCustomizationService( + PrefService* pref_service) + : pref_service_(pref_service) { + LoadCurrentTheme(); +} HomeBackgroundCustomizationService::~HomeBackgroundCustomizationService() {} void HomeBackgroundCustomizationService::Shutdown() {} +void HomeBackgroundCustomizationService::RegisterProfilePrefs( + PrefRegistrySimple* registry) { + registry->RegisterStringPref(prefs::kIosSavedThemeSpecificsIos, + std::string()); +} + std::optional<sync_pb::NtpCustomBackground> HomeBackgroundCustomizationService::GetCurrentCustomBackground() { if (!current_theme_.has_ntp_background()) { @@ -49,6 +64,7 @@ *current_theme_.mutable_ntp_background() = new_background; current_theme_.clear_user_color_theme(); + StoreCurrentTheme(); NotifyObserversOfBackgroundChange(); } @@ -62,9 +78,26 @@ *current_theme_.mutable_user_color_theme() = new_color_theme; current_theme_.clear_ntp_background(); + StoreCurrentTheme(); NotifyObserversOfBackgroundChange(); } +void HomeBackgroundCustomizationService::StoreCurrentTheme() { + std::string serialized = current_theme_.SerializeAsString(); + // Encode bytestring so it can be stored in a pref. + std::string encoded = base::Base64Encode(serialized); + pref_service_->SetString(prefs::kIosSavedThemeSpecificsIos, encoded); +} + +void HomeBackgroundCustomizationService::LoadCurrentTheme() { + std::string encoded = + pref_service_->GetString(prefs::kIosSavedThemeSpecificsIos); + // This pref is base64 encoded, so decode it first. + std::string serialized; + base::Base64Decode(encoded, &serialized); + current_theme_.ParseFromString(serialized); +} + void HomeBackgroundCustomizationService::AddObserver( HomeBackgroundCustomizationServiceObserver* observer) { observers_.AddObserver(observer);
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.h b/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.h index 0fc3128..1fa6f0c 100644 --- a/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.h +++ b/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.h
@@ -27,6 +27,8 @@ // BrowserStateKeyedServiceFactory implementation. std::unique_ptr<KeyedService> BuildServiceInstanceFor( web::BrowserState* context) const override; + void RegisterBrowserStatePrefs( + user_prefs::PrefRegistrySyncable* registry) override; }; #endif // IOS_CHROME_BROWSER_HOME_CUSTOMIZATION_MODEL_HOME_BACKGROUND_CUSTOMIZATION_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.mm b/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.mm index df7b910..7c6e108d 100644 --- a/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.mm +++ b/ios/chrome/browser/home_customization/model/home_background_customization_service_factory.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/home_customization/model/home_background_customization_service_factory.h" #import "base/no_destructor.h" +#import "components/pref_registry/pref_registry_syncable.h" #import "ios/chrome/browser/home_customization/model/home_background_customization_service.h" #import "ios/chrome/browser/shared/model/profile/profile_ios.h" @@ -33,5 +34,12 @@ std::unique_ptr<KeyedService> HomeBackgroundCustomizationServiceFactory::BuildServiceInstanceFor( web::BrowserState* context) const { - return std::make_unique<HomeBackgroundCustomizationService>(); + ProfileIOS* profile = ProfileIOS::FromBrowserState(context); + return std::make_unique<HomeBackgroundCustomizationService>( + profile->GetPrefs()); +} + +void HomeBackgroundCustomizationServiceFactory::RegisterBrowserStatePrefs( + user_prefs::PrefRegistrySyncable* registry) { + HomeBackgroundCustomizationService::RegisterProfilePrefs(registry); }
diff --git a/ios/chrome/browser/intelligence/bwg/model/BUILD.gn b/ios/chrome/browser/intelligence/bwg/model/BUILD.gn index ad661bb9..e314bb08 100644 --- a/ios/chrome/browser/intelligence/bwg/model/BUILD.gn +++ b/ios/chrome/browser/intelligence/bwg/model/BUILD.gn
@@ -9,8 +9,10 @@ ] deps = [ "//components/keyed_service/core", + "//components/prefs", "//components/signin/public/identity_manager", "//ios/chrome/browser/intelligence/bwg/metrics", + "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/public/provider/chrome/browser/bwg:bwg_api", @@ -43,6 +45,7 @@ deps = [ ":model", "//base/test:test_support", + "//components/prefs:test_support", "//components/signin/public/identity_manager:test_support", "//components/sync/base", "//components/sync/service", @@ -50,6 +53,7 @@ "//components/sync_preferences:test_support", "//ios/chrome/browser/intelligence/bwg/metrics", "//ios/chrome/browser/shared/model/application_context:application_context", + "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile/test", "//ios/chrome/browser/signin/model",
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_service.h b/ios/chrome/browser/intelligence/bwg/model/bwg_service.h index 739ace0..30251b3a 100644 --- a/ios/chrome/browser/intelligence/bwg/model/bwg_service.h +++ b/ios/chrome/browser/intelligence/bwg/model/bwg_service.h
@@ -15,12 +15,14 @@ namespace signin { class IdentityManager; } // namespace signin +class PrefService; // A browser-context keyed service for BWG. class BwgService : public KeyedService { public: BwgService(AuthenticationService* auth_service, - signin::IdentityManager* identity_manager); + signin::IdentityManager* identity_manager, + PrefService* pref_service); ~BwgService() override; // Presents the overlay on a given view controller. @@ -38,6 +40,9 @@ // Identity manager used to check account capabilities. raw_ptr<signin::IdentityManager> identity_manager_ = nullptr; + + // The PrefService associated with the Profile. + raw_ptr<PrefService> pref_service_ = nullptr; }; #endif // IOS_CHROME_BROWSER_INTELLIGENCE_BWG_MODEL_BWG_SERVICE_H_
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_service.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_service.mm index dece3b6..df741a9 100644 --- a/ios/chrome/browser/intelligence/bwg/model/bwg_service.mm +++ b/ios/chrome/browser/intelligence/bwg/model/bwg_service.mm
@@ -7,15 +7,19 @@ #import <memory> #import "base/metrics/histogram_functions.h" +#import "components/prefs/pref_service.h" #import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/public/provider/chrome/browser/bwg/bwg_api.h" BwgService::BwgService(AuthenticationService* auth_service, - signin::IdentityManager* identity_manager) { + signin::IdentityManager* identity_manager, + PrefService* pref_service) { auth_service_ = auth_service; identity_manager_ = identity_manager; + pref_service_ = pref_service; } BwgService::~BwgService() = default; @@ -28,16 +32,18 @@ } bool BwgService::IsEligibleForBWG() { - // TODO(crbug.com/419066154): Check other conditions, such as enterprise. - AccountCapabilities capabilities = identity_manager_ ->FindExtendedAccountInfo(identity_manager_->GetPrimaryAccountInfo( signin::ConsentLevel::kSignin)) .capabilities; - bool is_eligible = + bool can_use_model_execution = capabilities.can_use_model_execution_features() == signin::Tribool::kTrue; + bool is_disabled_by_policy = + pref_service_->GetInteger(prefs::kGeminiEnabledByPolicy) == 1; + + bool is_eligible = can_use_model_execution && !is_disabled_by_policy; base::UmaHistogramBoolean(kEligibilityHistogram, is_eligible);
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.mm index e72b787..e06a9ae 100644 --- a/ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.mm +++ b/ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.mm
@@ -24,7 +24,7 @@ ProfileIOS* profile = ProfileIOS::FromBrowserState(context); return std::make_unique<BwgService>( AuthenticationServiceFactory::GetForProfile(profile), - IdentityManagerFactory::GetForProfile(profile)); + IdentityManagerFactory::GetForProfile(profile), profile->GetPrefs()); } } // namespace
diff --git a/ios/chrome/browser/intelligence/bwg/model/bwg_service_unittest.mm b/ios/chrome/browser/intelligence/bwg/model/bwg_service_unittest.mm index 04f4002..fda59d4 100644 --- a/ios/chrome/browser/intelligence/bwg/model/bwg_service_unittest.mm +++ b/ios/chrome/browser/intelligence/bwg/model/bwg_service_unittest.mm
@@ -7,10 +7,13 @@ #import <memory> #import "base/test/metrics/histogram_tester.h" +#import "components/prefs/pref_registry_simple.h" +#import "components/prefs/testing_pref_service.h" #import "components/signin/public/identity_manager/account_capabilities_test_mutator.h" #import "components/signin/public/identity_manager/identity_test_environment.h" #import "ios/chrome/browser/intelligence/bwg/metrics/bwg_metrics.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" +#import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h" #import "ios/chrome/browser/signin/model/authentication_service.h" #import "ios/chrome/browser/signin/model/authentication_service_factory.h" @@ -35,10 +38,14 @@ std::make_unique<FakeAuthenticationServiceDelegate>())); profile_ = std::move(builder).Build(); + pref_service_ = std::make_unique<TestingPrefServiceSimple>(); + pref_service_->registry()->RegisterIntegerPref( + prefs::kGeminiEnabledByPolicy, 0); + auth_service_ = AuthenticationServiceFactory::GetForProfile(profile_.get()); identity_manager_ = identity_test_env_.identity_manager(); - bwg_service_ = - std::make_unique<BwgService>(auth_service_, identity_manager_); + bwg_service_ = std::make_unique<BwgService>( + auth_service_, identity_manager_, pref_service_.get()); } // Signs in a user and sets their model execution capability. @@ -62,6 +69,7 @@ // Profile and services that depend on the environment are declared next. std::unique_ptr<TestProfileIOS> profile_; std::unique_ptr<BwgService> bwg_service_; + std::unique_ptr<TestingPrefServiceSimple> pref_service_; raw_ptr<AuthenticationService> auth_service_; raw_ptr<signin::IdentityManager> identity_manager_; @@ -72,6 +80,7 @@ // account has the `can_use_model_execution_features` capability. TEST_F(BwgServiceTest, IsEligibleForBWG_WhenUserIsEligible) { SignInAndSetCapability(true); + pref_service_->SetInteger(prefs::kGeminiEnabledByPolicy, 0); EXPECT_TRUE(bwg_service_->IsEligibleForBWG()); histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, @@ -83,6 +92,18 @@ // capability is explicitly false. TEST_F(BwgServiceTest, IsEligibleForBWG_IneligibleByCapability) { SignInAndSetCapability(false); + pref_service_->SetInteger(prefs::kGeminiEnabledByPolicy, 0); + + EXPECT_FALSE(bwg_service_->IsEligibleForBWG()); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + /*sample=*/false, + /*expected_count=*/1); +} + +// Tests that a user is ineligible if the Gemini policy is disabled. +TEST_F(BwgServiceTest, IsEligibleForBWG_IneligibleByPolicy) { + SignInAndSetCapability(true); + pref_service_->SetInteger(prefs::kGeminiEnabledByPolicy, 1); EXPECT_FALSE(bwg_service_->IsEligibleForBWG()); histogram_tester_.ExpectUniqueSample(kEligibilityHistogram,
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm index 28444ae..33e299a 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_mediator.mm
@@ -229,6 +229,8 @@ _backgroundCustomizationServiceObserverBridge = std::make_unique<HomeBackgroundCustomizationServiceObserverBridge>( _backgroundCustomizationService, self); + // Make sure the intial background is set. + [self updateBackground]; } } @@ -393,29 +395,7 @@ #pragma mark - HomeBackgroundCustomizationServiceObserving - (void)onBackgroundChanged { - std::optional<sync_pb::NtpCustomBackground> background = - _backgroundCustomizationService->GetCurrentCustomBackground(); - - if (!background) { - [self.consumer setBackgroundImage:nil]; - return; - } - - GURL imageURL = GURL(background->url()); - - image_fetcher::ImageFetcher* imageFetcher = - _imageFetcherService->GetImageFetcher( - image_fetcher::ImageFetcherConfig::kDiskCacheOnly); - - __weak __typeof(self) weakSelf = self; - imageFetcher->FetchImage( - imageURL, - base::BindOnce(^(const gfx::Image& image, - const image_fetcher::RequestMetadata& metadata) { - [weakSelf handleBackgroundImageFetch:image]; - }), - // TODO (crbug.com/417234848): Add annotation. - image_fetcher::ImageFetcherParams(NO_TRAFFIC_ANNOTATION_YET, "Test")); + [self updateBackground]; } #pragma mark - Private @@ -481,6 +461,32 @@ email:_signedInIdentity.userEmail]; } +- (void)updateBackground { + std::optional<sync_pb::NtpCustomBackground> background = + _backgroundCustomizationService->GetCurrentCustomBackground(); + + if (!background) { + [self.consumer setBackgroundImage:nil]; + return; + } + + GURL imageURL = GURL(background->url()); + + image_fetcher::ImageFetcher* imageFetcher = + _imageFetcherService->GetImageFetcher( + image_fetcher::ImageFetcherConfig::kDiskCacheOnly); + + __weak __typeof(self) weakSelf = self; + imageFetcher->FetchImage( + imageURL, + base::BindOnce(^(const gfx::Image& image, + const image_fetcher::RequestMetadata& metadata) { + [weakSelf handleBackgroundImageFetch:image]; + }), + // TODO (crbug.com/417234848): Add annotation. + image_fetcher::ImageFetcherParams(NO_TRAFFIC_ANNOTATION_YET, "Test")); +} + // Helper method to handle the image response after fetching the background // image for the new tab page. - (void)handleBackgroundImageFetch:(const gfx::Image&)image {
diff --git a/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm b/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm index 9ad05ed..0ead817 100644 --- a/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm +++ b/ios/chrome/browser/policy/model/configuration_policy_handler_list_factory.mm
@@ -172,6 +172,9 @@ { policy::key::kAIModeSettings, omnibox::kAIModeSettings, base::Value::Type::INTEGER }, + { policy::key::kGeminiSettings, + prefs::kGeminiEnabledByPolicy, + base::Value::Type::INTEGER }, }; // clang-format on
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/destination_drag_handler.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/destination_drag_handler.swift index 9643fcc..610e339 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/destination_drag_handler.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/destination_drag_handler.swift
@@ -6,6 +6,7 @@ /// Class to handle destination drag interactions in the overflow menu /// customization flow. +@MainActor class DestinationDragHandler: ObservableObject { /// Collection of data for the current drag interaction. struct CurrentDragData { @@ -161,9 +162,9 @@ } extension DestinationDragHandler: DidEndItemProviderDelegate { - func didEndItemProviderDidEnd(_ provider: DidEndItemProvider) { + func didEndItemProviderDidEnd(_ providerID: UUID) { providers = providers.filter { container in - container.provider != nil && container.provider != provider + container.provider != nil && container.providerID() != providerID } if providers.isEmpty { endDrag() @@ -171,17 +172,21 @@ } } -protocol DidEndItemProviderDelegate: AnyObject { +@MainActor +protocol DidEndItemProviderDelegate: AnyObject, Sendable { /// Alerts the delegate when the item provider is being deinitialized. - func didEndItemProviderDidEnd(_ provider: DidEndItemProvider) + func didEndItemProviderDidEnd(_ providerID: UUID) } /// A custom item provider class that alerts its delegate when it is about to /// be de-initialized. class DidEndItemProvider: NSItemProvider { + let id: UUID = UUID.init() weak var delegate: DidEndItemProviderDelegate? deinit { - delegate?.didEndItemProviderDidEnd(self) + Task { @MainActor[weak delegate, id] in + delegate?.didEndItemProviderDidEnd(id) + } } } @@ -192,4 +197,7 @@ init(provider: DidEndItemProvider?) { self.provider = provider } + func providerID() -> UUID? { + self.provider?.id + } }
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_list.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_list.swift index 4a219d4b..c252bcca 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_list.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_list.swift
@@ -62,7 +62,7 @@ /// `PreferenceKey` to track the leading offset of the scroll view. struct ScrollViewLeadingOffset: PreferenceKey { - static var defaultValue: CGFloat = .greatestFiniteMagnitude + static let defaultValue: CGFloat = .greatestFiniteMagnitude static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = min(value, nextValue()) } @@ -72,7 +72,7 @@ /// can be transformed to other coordinate space by geometry reader. struct HighlightedDestinationBounds: PreferenceKey { typealias Value = Anchor<CGRect>? - static var defaultValue: Value = nil + static let defaultValue: Value = nil static func reduce(value: inout Value, nextValue: () -> Value) { // AnchorPreference might be nil in the middle of layout. if let next = nextValue() { @@ -140,16 +140,18 @@ ) .onPreferenceChange(ScrollViewLeadingOffset.self) { newOffset in // Only alert the handler if scroll tracking has started. - if let listOffset = listOffset, - newOffset != listOffset - { - metricsHandler?.popupMenuScrolledHorizontally() - } - // Only update the offset if scroll tracking has started or the newOffset - // is approximately 0 (this starts scroll tracking). In RTL mode, the - // offset is not exactly 0, so a strict comparison won't work. - if listOffset != nil || (listOffset == nil && abs(newOffset) < 1e-9) { - listOffset = newOffset + Task { @MainActor in + if let listOffset = listOffset, + newOffset != listOffset + { + metricsHandler?.popupMenuScrolledHorizontally() + } + // Only update the offset if scroll tracking has started or the newOffset + // is approximately 0 (this starts scroll tracking). In RTL mode, the + // offset is not exactly 0, so a strict comparison won't work. + if listOffset != nil || (listOffset == nil && abs(newOffset) < 1e-9) { + listOffset = newOffset + } } } }
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_view.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_view.swift index 8edc581d..f13fa5388 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_view.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_destination_view.swift
@@ -29,7 +29,7 @@ /// `PreferenceKey` holding the frame of the icon in the destination view. struct IconFramePreferenceKey: PreferenceKey { - static var defaultValue: CGRect = .null + static let defaultValue: CGRect = .null static func reduce(value: inout CGRect, nextValue: () -> CGRect) { value = CGRectUnion(value, nextValue()) } @@ -162,7 +162,9 @@ ) { $0 } } .onPreferenceChange(IconFramePreferenceKey.self) { newFrame in - iconFrame = newFrame + Task { @MainActor in + iconFrame = newFrame + } } }
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_ui_configuration.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_ui_configuration.swift index 16de83a..ea670cf 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_ui_configuration.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_ui_configuration.swift
@@ -5,6 +5,7 @@ import SwiftUI /// Holds UI data necessary to display the overflow menu. +@MainActor @objcMembers public class OverflowMenuUIConfiguration: NSObject, ObservableObject { @Published public var presentingViewControllerHorizontalSizeClass: UserInterfaceSizeClass @Published public var presentingViewControllerVerticalSizeClass: UserInterfaceSizeClass
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view.swift index b2c74ae..19090d52 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view.swift
@@ -4,6 +4,7 @@ import SwiftUI +@MainActor struct OverflowMenuView: View { @ObservedObject var model: OverflowMenuModel @@ -45,9 +46,11 @@ } .background(Color(.systemGroupedBackground).edgesIgnoringSafeArea(.all)) .onPreferenceChange(OverflowMenuDestinationList.HighlightedDestinationBounds.self) { pref in - highlightedDestinationBounds = pref + Task { @MainActor in + highlightedDestinationBounds = pref + } } - .onGeometryChange(for: CGRect?.self) { proxy in + .onGeometryChange(for: CGRect?.self) { [highlightedDestinationBounds] proxy in if let highlightedDestinationBounds = highlightedDestinationBounds { return proxy[highlightedDestinationBounds] }
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view_provider.swift b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view_provider.swift index c6ddf52..0e8829a 100644 --- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view_provider.swift +++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_view_provider.swift
@@ -7,6 +7,7 @@ // A provider to provide the SwiftUI OverflowMenuView to Objective C. This is // necessary because Objective C can't see SwiftUI types. +@MainActor @objcMembers public class OverflowMenuViewProvider: NSObject { public static func makeViewController( withModel model: OverflowMenuModel,
diff --git a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm index 636f067..dade4f6 100644 --- a/ios/chrome/browser/shared/model/prefs/browser_prefs.mm +++ b/ios/chrome/browser/shared/model/prefs/browser_prefs.mm
@@ -1037,6 +1037,8 @@ registry->RegisterIntegerPref(omnibox::kAIModeSettings, 0); + registry->RegisterIntegerPref(prefs::kGeminiEnabledByPolicy, 0); + // Deprecated 09/2024 (migrated to localState prefs). registry->RegisterBooleanPref(prefs::kIncognitoInterstitialEnabled, false);
diff --git a/ios/chrome/browser/shared/model/prefs/pref_names.h b/ios/chrome/browser/shared/model/prefs/pref_names.h index 11b283e..7c6491a 100644 --- a/ios/chrome/browser/shared/model/prefs/pref_names.h +++ b/ios/chrome/browser/shared/model/prefs/pref_names.h
@@ -388,6 +388,11 @@ inline constexpr char kIosChooseFromDriveFilePickerPolicySettings[] = "ios.choose_from_drive.file_picker_policy"; +// Preference to store the current ThemeSpecificsIos for the user's background +// choices. +inline constexpr char kIosSavedThemeSpecificsIos[] = + "ios.saved_theme_specifics_ios"; + // String preference containing the default account to use for saving images to // Google Photos. inline constexpr char kIosSaveToPhotosDefaultGaiaId[] = @@ -780,6 +785,10 @@ // triggered right after the FRE. inline constexpr char kNextSSORecallTime[] = "ios.next_sso_recall_time"; +// An integer determining the enabled status of Gemini by policy. +// 0 means Gemini is enabled (default), and 1 means it's disabled. +inline constexpr char kGeminiEnabledByPolicy[] = "ios.gemini_enabled_by_policy"; + } // namespace prefs #endif // IOS_CHROME_BROWSER_SHARED_MODEL_PREFS_PREF_NAMES_H_
diff --git a/ios/chrome/browser/shared/public/commands/autofill_commands.h b/ios/chrome/browser/shared/public/commands/autofill_commands.h index 53f545a..be10536 100644 --- a/ios/chrome/browser/shared/public/commands/autofill_commands.h +++ b/ios/chrome/browser/shared/public/commands/autofill_commands.h
@@ -38,7 +38,7 @@ - (void)showPlusAddressesBottomSheet; // Commands to manage save card bottomsheet. -- (void)showSaveCardBottomSheet; +- (void)showSaveCardBottomSheetOnOriginWebState:(web::WebState*)originWebState; - (void)dismissSaveCardBottomSheet; // Sends a command to show the VCN enrollment Bottom Sheet.
diff --git a/ios/chrome/browser/widget_kit/model/user_defaults_widget_store.swift b/ios/chrome/browser/widget_kit/model/user_defaults_widget_store.swift index a409d74..1825ddf 100644 --- a/ios/chrome/browser/widget_kit/model/user_defaults_widget_store.swift +++ b/ios/chrome/browser/widget_kit/model/user_defaults_widget_store.swift
@@ -5,23 +5,19 @@ import Foundation /// An object that stores and retrieves the widget configurations from user defaults. -public struct UserDefaultsWidgetStore { +public struct UserDefaultsWidgetStore: Sendable { /// The key that the current widget configurations are stored under in the user defaults. private let widgetInfoKey = "com.google.chrome.ios.widgets.widget-info" - // Use UserDefaults.standard because this information only needs to be stored and retrieved from - // the main app. - private let userDefaults = UserDefaults.standard - public func storeWidgetInfo(_ info: [String]) throws { let encoder = JSONEncoder() let data = try encoder.encode(info) - userDefaults.set(data, forKey: widgetInfoKey) + UserDefaults.standard.set(data, forKey: widgetInfoKey) } public func retrieveStoredWidgetInfo() -> Result<[String], Error> { - guard let data = userDefaults.data(forKey: widgetInfoKey) else { + guard let data = UserDefaults.standard.data(forKey: widgetInfoKey) else { // If there is no stored data, return an empty array. return .success([]) }
diff --git a/ios/chrome/browser/widget_kit/model/widget_metrics_logger.swift b/ios/chrome/browser/widget_kit/model/widget_metrics_logger.swift index 61db97e..3f65729 100644 --- a/ios/chrome/browser/widget_kit/model/widget_metrics_logger.swift +++ b/ios/chrome/browser/widget_kit/model/widget_metrics_logger.swift
@@ -17,18 +17,21 @@ /// information about which widget was installed. /// /// This property must be set before the `logInstalledWidgets` method is called. + @MainActor @objc public static var widgetInstalledCallback: ((String) -> Void)? = nil /// A callback to be called when a widget uninstall is detected. This callback is passed the /// kind about which widget was uninstalled. /// /// This property must be set before the `logInstalledWidgets` method is called. + @MainActor @objc public static var widgetUninstalledCallback: ((String) -> Void)? = nil /// A callback to be called when a widget in use is detected. This callback is passed the /// kind about which widget is in use. /// /// This property must be set before the `logInstalledWidgets` method is called. + @MainActor @objc public static var widgetCurrentCallback: ((String) -> Void)? = nil /// Logs metrics if the user has installed or uninstalled a widget since the last check. @@ -57,8 +60,10 @@ } // Log current widgets. - for widget in currentWidgets { - widgetCurrentCallback?(widget) + Task { @MainActor in + for widget in currentWidgets { + widgetCurrentCallback?(widget) + } } guard let storedWidgets = try? store.retrieveStoredWidgetInfo().get() else { @@ -81,8 +86,10 @@ installedWidgets.remove(at: index) } } - for installedWidget in installedWidgets { - widgetInstalledCallback?(installedWidget) + Task { @MainActor in + for installedWidget in installedWidgets { + widgetInstalledCallback?(installedWidget) + } } // Stored widgets minus current widgets are uninstallations. @@ -92,8 +99,10 @@ uninstalledWidgets.remove(at: index) } } - for uninstalledWidget in uninstalledWidgets { - widgetUninstalledCallback?(uninstalledWidget) + Task { @MainActor in + for uninstalledWidget in uninstalledWidgets { + widgetUninstalledCallback?(uninstalledWidget) + } } } }
diff --git a/ios/chrome/test/data/policy/policy_test_bundle_data.filelist b/ios/chrome/test/data/policy/policy_test_bundle_data.filelist index 6710305..acab5df 100644 --- a/ios/chrome/test/data/policy/policy_test_bundle_data.filelist +++ b/ios/chrome/test/data/policy/policy_test_bundle_data.filelist
@@ -43,6 +43,7 @@ //ios/chrome/test/data/policy/pref_mapping/EnableExperimentalPolicies.json //ios/chrome/test/data/policy/pref_mapping/EnterpriseRealTimeUrlCheckMode.json //ios/chrome/test/data/policy/pref_mapping/FilePickerChooseFromDriveSettings.json +//ios/chrome/test/data/policy/pref_mapping/GeminiSettings.json //ios/chrome/test/data/policy/pref_mapping/GenAiDefaultSettings.json //ios/chrome/test/data/policy/pref_mapping/IdleTimeout.json //ios/chrome/test/data/policy/pref_mapping/IdleTimeoutActions.json
diff --git a/ios/chrome/test/data/policy/pref_mapping/GeminiSettings.json b/ios/chrome/test/data/policy/pref_mapping/GeminiSettings.json new file mode 100644 index 0000000..1fa0bc6 --- /dev/null +++ b/ios/chrome/test/data/policy/pref_mapping/GeminiSettings.json
@@ -0,0 +1,15 @@ +[ + { + "os": [ + "ios" + ], + "simple_policy_pref_mapping_test": { + "pref_name": "ios.gemini_enabled_by_policy", + "default_value": 0, + "values_to_test": [ + 0, + 1 + ] + } + } +]
diff --git a/ios/chrome/widget_kit_extension/deleted_account_views.swift b/ios/chrome/widget_kit_extension/deleted_account_views.swift index f84842d..55e920be 100644 --- a/ios/chrome/widget_kit_extension/deleted_account_views.swift +++ b/ios/chrome/widget_kit_extension/deleted_account_views.swift
@@ -17,6 +17,7 @@ sharedDefaults.set(true, forKey: "DeletedAccountUiDisplayed") } +@MainActor func SmallWidgetDeletedAccountView() -> some View { VStack { ZStack { @@ -39,6 +40,7 @@ } } +@MainActor func MediumWidgetDeletedAccountView() -> some View { VStack { ZStack {
diff --git a/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift b/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift index 3028de3..e2c82c9 100644 --- a/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift +++ b/ios/chrome/widget_kit_extension/lockscreen_launcher_widget.swift
@@ -63,6 +63,7 @@ } } + @MainActor func lockScreenWidgetBackground() -> some View { if #available(iOS 16.0, *) { return AccessoryWidgetBackground() @@ -90,6 +91,7 @@ } } + @MainActor func lockscreenLauncherWidgetConfiguration( ofKind kind: String, forType type: LockscreenLauncherWidgetType ) -> some WidgetConfiguration {
diff --git a/ios/chrome/widget_kit_extension/main.swift b/ios/chrome/widget_kit_extension/main.swift index c247d25..a8b4a6e 100644 --- a/ios/chrome/widget_kit_extension/main.swift +++ b/ios/chrome/widget_kit_extension/main.swift
@@ -10,7 +10,9 @@ struct ChromeWidgetsMain { // Bool telling if widgets for multiprofile is enabled. - static var WidgetForMIMAvailable: Bool = false + // Use an external synchronization mechanism to modify the value because `nonisolated(unsafe)` + // opts out of concurrency checking. + nonisolated(unsafe) static var WidgetForMIMAvailable: Bool = false static func main() { CrashHelper.configure()
diff --git a/ios/chrome/widget_kit_extension/select_profile_intent.swift b/ios/chrome/widget_kit_extension/select_profile_intent.swift index 5a21eed..a7c08d6 100644 --- a/ios/chrome/widget_kit_extension/select_profile_intent.swift +++ b/ios/chrome/widget_kit_extension/select_profile_intent.swift
@@ -43,8 +43,8 @@ let id: String let gaia: String - static var typeDisplayRepresentation: TypeDisplayRepresentation = "Account" - static var defaultQuery = AccountQuery() + static let typeDisplayRepresentation: TypeDisplayRepresentation = "Account" + static let defaultQuery = AccountQuery() var displayRepresentation: DisplayRepresentation { DisplayRepresentation(title: "\(id)") @@ -75,8 +75,9 @@ @available(iOS 17, *) struct SelectAccountIntent: WidgetConfigurationIntent { - static var title: LocalizedStringResource = "Select Account" - static var description = IntentDescription("Selects the account to display shortcuts for.") + static let title: LocalizedStringResource = "Select Account" + static let description = IntentDescription( + "Selects the account to display shortcuts for.") @Parameter(title: "IDS_IOS_WIDGET_KIT_EXTENSION_SELECT_ACCOUNT_LABEL") var account: AccountDetail?
diff --git a/ios/third_party/earl_grey2/src b/ios/third_party/earl_grey2/src index 4d03903..26e72194 160000 --- a/ios/third_party/earl_grey2/src +++ b/ios/third_party/earl_grey2/src
@@ -1 +1 @@ -Subproject commit 4d03903575101220da2ab2262376d2b1b9a14dc4 +Subproject commit 26e72194d8863202aeaad2f124f7964ae3f3934f
diff --git a/media/formats/webm/webm_parser.cc b/media/formats/webm/webm_parser.cc index 831e6d6..1f641d9a 100644 --- a/media/formats/webm/webm_parser.cc +++ b/media/formats/webm/webm_parser.cc
@@ -1,6 +1,13 @@ // Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// +// This file contains code to parse WebM file elements. It was created +// from information in the Matroska spec. +// http://www.matroska.org/technical/specs/index.html +// +// WebM Container Guidelines is at https://www.webmproject.org/docs/container/ +// WebM Encryption spec is at: https://www.webmproject.org/docs/webm-encryption/ #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. @@ -9,29 +16,20 @@ #include "media/formats/webm/webm_parser.h" -#include <array> - -#include "base/containers/span.h" -#include "base/memory/raw_span.h" - -// This file contains code to parse WebM file elements. It was created -// from information in the Matroska spec. -// http://www.matroska.org/technical/specs/index.html -// -// WebM Container Guidelines is at https://www.webmproject.org/docs/container/ -// WebM Encryption spec is at: https://www.webmproject.org/docs/webm-encryption/ - #include <stddef.h> #include <algorithm> +#include <array> #include <cstring> #include <iomanip> #include <limits> #include "base/check_op.h" +#include "base/containers/span.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" -#include "base/notreached.h" +#include "base/memory/raw_span.h" +#include "base/notimplemented.h" #include "base/numerics/safe_conversions.h" #include "media/formats/webm/webm_constants.h"
diff --git a/net/data/ssl/chrome_root_store/additional.certs b/net/data/ssl/chrome_root_store/additional.certs index 5008efb..441ffcf6 100644 --- a/net/data/ssl/chrome_root_store/additional.certs +++ b/net/data/ssl/chrome_root_store/additional.certs
@@ -4621,3 +4621,1040 @@ zJfmxHioB7EtWB8BOTY9ZFJZXGDNZqqM0IrIHDsbUJLwPeFJOrFCUVwVcscwh5FI c2IYWCY6wNpb4E8FkrY= -----END CERTIFICATE----- + +SHA-256 hash: b10b6f00e609509e8700f6d34687a2bfce38ea05a8fdf1cdc40c3a2a0d0d0e45 +Subject: "CN=WR1, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R1, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:d9:e2:c2:d2:04:8a:04:74:b6:27:a2:6d:08:68:a7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WR1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:cf:6e:36:16:8a:b7:2b:ee:46:98:03:1d:53:70: + 0f:77:ee:a3:4b:a0:72:be:8f:23:2d:c2:47:c6:8f: + 5c:8d:f9:3d:e6:1a:8e:ee:33:22:0d:c9:11:48:b8: + b0:62:ce:f4:69:0d:72:02:7d:de:d5:26:0f:c3:6e: + 9b:cf:7e:0e:d7:20:cf:c6:90:3b:a3:82:06:da:3a: + 9d:ff:6c:56:bf:dc:e9:61:94:45:e4:69:bc:4f:0f: + c9:13:c0:ad:61:44:72:20:81:d0:0f:2b:9e:68:6a: + 62:6a:8f:8a:22:57:79:69:2b:e2:24:33:7e:76:63: + 2c:5d:bc:51:69:7e:23:07:b1:ff:76:81:f1:ee:b8: + 58:b5:6b:35:15:ef:a1:e6:48:28:39:97:31:d9:07: + 1f:95:a7:9e:ae:cf:98:bc:9e:8d:8a:03:e1:b0:97: + 4d:50:6f:93:4c:4a:1f:f8:db:7d:f1:90:99:15:7f: + e3:96:ed:ee:31:81:ea:72:3d:52:1d:df:25:64:a5: + 0b:70:aa:9e:e8:a8:b9:47:c8:a7:5a:10:25:60:6f: + 42:e1:d7:3f:e7:8f:0c:f0:c2:83:46:33:20:e6:4b: + 77:04:76:a1:68:a7:5d:15:18:ef:d8:28:77:35:ad: + 0e:ad:46:e4:62:6e:e2:aa:f8:cc:ef:37:7e:0f:26: + b3:07 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 66:69:49:D4:DE:2A:9C:91:03:CF:89:0E:24:B8:0E:30:03:6E:88:2E + X509v3 Authority Key Identifier: + keyid:E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r1.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r1.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: sha256WithRSAEncryption + 4e:e6:b3:08:11:20:91:60:27:f9:51:90:4d:02:18:ee:b8:c1: + 89:d5:22:84:97:e6:d6:df:e6:4e:3a:3b:29:04:7e:de:20:f1: + e2:8d:8b:d3:aa:1e:17:44:37:c2:92:98:a5:08:08:fd:37:8c: + a9:49:58:31:64:26:65:b5:8f:13:43:d7:f2:97:ec:54:01:39: + 13:9b:55:3a:38:77:e1:b3:40:27:00:cf:56:7b:19:54:9c:33: + 37:79:f0:e4:11:90:ee:cc:51:b2:91:73:21:c3:3f:a9:b6:d3: + a4:d7:97:7f:d2:08:e1:6b:24:db:e4:ef:e8:54:95:15:95:0b: + df:fd:2e:1e:b6:9d:6e:bb:83:5a:34:50:e0:86:7b:99:8a:8a: + 88:4a:a4:d3:c7:69:39:9f:93:98:1c:f0:ca:41:06:cb:5f:c8: + 5d:b7:ab:6f:a0:29:d5:24:a7:9f:6f:91:23:bb:7a:37:f7:ea: + 3c:2a:f0:c0:58:e9:f2:48:35:1b:a7:ad:44:04:c6:05:a3:d8: + 0b:1f:86:8c:93:05:3d:7f:a4:f7:b0:25:be:88:f7:ff:df:12: + be:a7:5e:80:b3:d8:10:f8:ef:c5:47:25:1e:98:8a:2c:3e:b7: + 34:c9:95:6a:b5:50:75:d2:0b:ea:43:af:4d:ee:64:d2:99:f1: + 46:74:7e:9a:77:46:1c:84:1c:ef:b4:cb:6d:c6:45:7a:36:b9: + e8:fc:a7:95:2a:a6:7a:be:7b:f1:ce:c2:06:b3:ea:a3:50:55: + 98:fc:96:50:af:af:ea:c1:ae:ce:ce:cc:ab:b4:10:6b:15:6c: + e3:bd:74:70:8f:cc:a4:fa:75:a2:fc:4c:56:dd:7b:10:d2:b1: + 2e:4d:f8:2e:91:0a:00:a5:66:ab:09:f3:6c:71:d1:8e:15:cd: + 78:20:bd:f3:85:c3:3b:02:c4:a7:42:b8:33:31:e5:f1:93:96: + 25:00:1a:90:27:55:94:50:be:3f:20:37:18:fd:89:5f:f4:0b: + a2:a5:8d:1c:6b:8d:f5:cf:6f:2c:e6:c3:84:75:6c:fc:bf:ba: + e4:37:be:39:d9:e7:8e:91:46:23:dc:71:b6:c3:72:46:cc:9a: + 1d:d1:40:7f:9c:fb:ba:53:a8:5c:35:e4:1c:20:9e:8f:f1:21: + b3:97:68:71:17:8d:b7:5e:96:db:16:c7:fc:40:6e:8a:b2:6b: + 3b:31:44:da:bb:40:2f:19:2c:97:54:dd:12:33:9f:20:a5:ce: + 25:f5:2a:41:e5:48:e7:e8:40:ed:5f:a7:d7:e0:3f:9f:b3:69: + 83:44:be:e4:e0:f2:b5:68:79:5d:6e:78:71:c3:75:76:b2:67: + 30:ae:78:b6:da:33:87:47 +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIQf9niwtIEigR0tieibQhopzANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw +MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl +cnZpY2VzMQwwCgYDVQQDEwNXUjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQDPbjYWircr7kaYAx1TcA937qNLoHK+jyMtwkfGj1yN+T3mGo7uMyINyRFI +uLBizvRpDXICfd7VJg/DbpvPfg7XIM/GkDujggbaOp3/bFa/3OlhlEXkabxPD8kT +wK1hRHIggdAPK55oamJqj4oiV3lpK+IkM352YyxdvFFpfiMHsf92gfHuuFi1azUV +76HmSCg5lzHZBx+Vp56uz5i8no2KA+Gwl01Qb5NMSh/4233xkJkVf+OW7e4xgepy +PVId3yVkpQtwqp7oqLlHyKdaECVgb0Lh1z/njwzwwoNGMyDmS3cEdqFop10VGO/Y +KHc1rQ6tRuRibuKq+MzvN34PJrMHAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBRmaUnU3iqckQPPiQ4kuA4wA26ILjAfBgNVHSMEGDAWgBTk +rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG +GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw +Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq +hkiG9w0BAQsFAAOCAgEATuazCBEgkWAn+VGQTQIY7rjBidUihJfm1t/mTjo7KQR+ +3iDx4o2L06oeF0Q3wpKYpQgI/TeMqUlYMWQmZbWPE0PX8pfsVAE5E5tVOjh34bNA +JwDPVnsZVJwzN3nw5BGQ7sxRspFzIcM/qbbTpNeXf9II4Wsk2+Tv6FSVFZUL3/0u +HradbruDWjRQ4IZ7mYqKiEqk08dpOZ+TmBzwykEGy1/IXberb6Ap1SSnn2+RI7t6 +N/fqPCrwwFjp8kg1G6etRATGBaPYCx+GjJMFPX+k97Alvoj3/98SvqdegLPYEPjv +xUclHpiKLD63NMmVarVQddIL6kOvTe5k0pnxRnR+mndGHIQc77TLbcZFeja56Pyn +lSqmer578c7CBrPqo1BVmPyWUK+v6sGuzs7Mq7QQaxVs4710cI/MpPp1ovxMVt17 +ENKxLk34LpEKAKVmqwnzbHHRjhXNeCC984XDOwLEp0K4MzHl8ZOWJQAakCdVlFC+ +PyA3GP2JX/QLoqWNHGuN9c9vLObDhHVs/L+65De+OdnnjpFGI9xxtsNyRsyaHdFA +f5z7ulOoXDXkHCCej/Ehs5docReNt16W2xbH/EBuirJrOzFE2rtALxksl1TdEjOf +IKXOJfUqQeVI5+hA7V+n1+A/n7Npg0S+5ODytWh5XW54ccN1drJnMK54ttozh0c= +-----END CERTIFICATE----- + +SHA-256 hash: e6fe22bf45e4f0d3b85c59e02c0f495418e1eb8d3210f788d48cd5e1cb547cd4 +Subject: "CN=WR2, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R1, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f0:05:a0:7c:4c:de:d1:00:ad:9d:66:a5:10:7b:98 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WR2 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a9:ff:9c:7f:45:1e:70:a8:53:9f:ca:d9:e5:0d: + de:46:57:57:7d:bc:8f:9a:5a:ac:46:f1:84:9a:bb: + 91:db:c9:fb:2f:01:fb:92:09:00:16:5e:a0:1c:f8: + c1:ab:f9:78:2f:4a:cc:d8:85:a2:d8:59:3c:0e:d3: + 18:fb:b1:f5:24:0d:26:ee:b6:5b:64:76:7c:14:c7: + 2f:7a:ce:a8:4c:b7:f4:d9:08:fc:df:87:23:35:20: + a8:e2:69:e2:8c:4e:3f:b1:59:fa:60:a2:1e:b3:c9: + 20:53:19:82:ca:36:53:6d:60:4d:e9:00:91:fc:76: + 8d:5c:08:0f:0a:c2:dc:f1:73:6b:c5:13:6e:0a:4f: + 7a:c2:f2:02:1c:2e:b4:63:83:da:31:f6:2d:75:30: + b2:fb:ab:c2:6e:db:a9:c0:0e:b9:f9:67:d4:c3:25: + 57:74:eb:05:b4:e9:8e:b5:de:28:cd:cc:7a:14:e4: + 71:03:cb:4d:61:2e:61:57:c5:19:a9:0b:98:84:1a: + e8:79:29:d9:b2:8d:2f:ff:57:6a:66:e0:ce:ab:95: + a8:29:96:63:70:12:67:1e:3a:e1:db:b0:21:71:d7: + 7c:9e:fd:aa:17:6e:fe:2b:fb:38:17:14:d1:66:a7: + af:9a:b5:70:cc:c8:63:81:3a:8c:c0:2a:a9:76:37: + ce:e3 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + DE:1B:1E:ED:79:15:D4:3E:37:24:C3:21:BB:EC:34:39:6D:42:B2:30 + X509v3 Authority Key Identifier: + keyid:E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r1.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r1.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: sha256WithRSAEncryption + 45:75:8b:e5:1f:3b:44:13:96:1a:ab:58:f1:35:c9:6f:3d:d2: + d0:33:4a:86:33:ba:57:51:4f:ee:c4:34:da:16:12:4c:bf:13: + 9f:0d:d4:54:e9:48:79:c0:30:3c:94:25:f2:1a:f4:ba:32:94: + b6:33:72:0b:85:ee:09:11:25:34:94:e1:6f:42:db:82:9b:7b: + 7f:2a:9a:a9:ff:7f:a9:d2:de:4a:20:cb:b3:fb:03:03:b8:f8: + 07:05:da:59:92:2f:18:46:98:ce:af:72:be:24:26:b1:1e:00: + 4d:bd:08:ad:93:41:44:0a:bb:c7:d5:01:85:bf:93:57:e3:df: + 74:12:53:0e:11:25:d3:9b:dc:de:cb:27:6e:b3:c2:b9:33:62: + 39:c2:e0:35:e1:5b:a7:09:2e:19:cb:91:2a:76:5c:f1:df:ca: + 23:84:40:a5:6f:ff:9a:41:e0:b5:ef:32:d1:85:ae:af:25:09: + f0:62:c5:6e:c2:c8:6e:32:fd:b8:da:e2:ce:4a:91:4a:f3:85: + 55:4e:b1:75:d6:48:33:2f:6f:84:d9:12:5c:9f:d4:71:98:63: + 25:8d:69:5c:0a:6b:7d:f2:41:bd:e8:bb:8f:e4:22:d7:9d:65: + 45:e8:4c:0a:87:da:e9:60:66:88:0e:1f:c7:e1:4e:56:c5:76: + ff:b4:7a:57:69:f2:02:22:09:26:41:1d:da:74:a2:e5:29:f3: + c4:9a:e5:5d:d6:aa:7a:fd:e1:b7:2b:66:38:fb:e8:29:66:ba: + ef:a0:13:2f:f8:73:7e:f0:da:40:11:1c:5d:dd:8f:a6:fc:be: + db:be:56:f8:32:9c:1f:41:41:6d:7e:b6:c5:eb:c6:8b:36:b7: + 17:8c:9d:cf:19:7a:34:9f:21:93:c4:7e:74:35:d2:aa:fd:4c: + 6d:14:f5:c9:b0:79:5b:49:3c:f3:bf:17:48:e8:ef:9a:26:13: + 0c:87:f2:73:d6:9c:c5:52:6b:63:f7:32:90:78:a9:6b:eb:5e: + d6:93:a1:bf:bc:18:3d:8b:59:f6:8a:c6:05:5e:52:18:e2:66: + e0:da:c1:dc:ad:5a:25:aa:f4:45:fc:f1:0b:78:a4:af:b0:f2: + 73:a4:30:a8:34:c1:53:7f:42:96:e5:48:41:eb:90:46:0c:06: + dc:cb:92:c6:5e:f3:44:44:43:46:29:46:a0:a6:fc:b9:8e:39: + 27:39:b1:5a:e2:b1:ad:fc:13:ff:8e:fc:26:e1:d4:fe:84:f1: + 50:5a:8e:97:6b:2d:2a:79:fb:40:64:ea:f3:3d:bd:5b:e1:a0: + 04:b0:97:48:1c:42:f5:ea:5a:1c:cd:26:c8:51:ff:14:99:67: + 89:72:5f:1d:ec:ad:5a:dd +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIQf/AFoHxM3tEArZ1mpRB7mDANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw +MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl +cnZpY2VzMQwwCgYDVQQDEwNXUjIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCp/5x/RR5wqFOfytnlDd5GV1d9vI+aWqxG8YSau5HbyfsvAfuSCQAWXqAc ++MGr+XgvSszYhaLYWTwO0xj7sfUkDSbutltkdnwUxy96zqhMt/TZCPzfhyM1IKji +aeKMTj+xWfpgoh6zySBTGYLKNlNtYE3pAJH8do1cCA8Kwtzxc2vFE24KT3rC8gIc +LrRjg9ox9i11MLL7q8Ju26nADrn5Z9TDJVd06wW06Y613ijNzHoU5HEDy01hLmFX +xRmpC5iEGuh5KdmyjS//V2pm4M6rlagplmNwEmceOuHbsCFx13ye/aoXbv4r+zgX +FNFmp6+atXDMyGOBOozAKql2N87jAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBTeGx7teRXUPjckwyG77DQ5bUKyMDAfBgNVHSMEGDAWgBTk +rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG +GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw +Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq +hkiG9w0BAQsFAAOCAgEARXWL5R87RBOWGqtY8TXJbz3S0DNKhjO6V1FP7sQ02hYS +TL8Tnw3UVOlIecAwPJQl8hr0ujKUtjNyC4XuCRElNJThb0Lbgpt7fyqaqf9/qdLe +SiDLs/sDA7j4BwXaWZIvGEaYzq9yviQmsR4ATb0IrZNBRAq7x9UBhb+TV+PfdBJT +DhEl05vc3ssnbrPCuTNiOcLgNeFbpwkuGcuRKnZc8d/KI4RApW//mkHgte8y0YWu +ryUJ8GLFbsLIbjL9uNrizkqRSvOFVU6xddZIMy9vhNkSXJ/UcZhjJY1pXAprffJB +vei7j+Qi151lRehMCofa6WBmiA4fx+FOVsV2/7R6V2nyAiIJJkEd2nSi5SnzxJrl +Xdaqev3htytmOPvoKWa676ATL/hzfvDaQBEcXd2Ppvy+275W+DKcH0FBbX62xevG +iza3F4ydzxl6NJ8hk8R+dDXSqv1MbRT1ybB5W0k8878XSOjvmiYTDIfyc9acxVJr +Y/cykHipa+te1pOhv7wYPYtZ9orGBV5SGOJm4NrB3K1aJar0RfzxC3ikr7Dyc6Qw +qDTBU39CluVIQeuQRgwG3MuSxl7zRERDRilGoKb8uY45JzmxWuKxrfwT/478JuHU +/oTxUFqOl2stKnn7QGTq8z29W+GgBLCXSBxC9epaHM0myFH/FJlniXJfHeytWt0= +-----END CERTIFICATE----- + +SHA-256 hash: 2fe357db13751ff9160e87354975b3407498f41c9bd16a48657866e6e5a9b4c7 +Subject: "CN=WR3, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R1, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f0:05:a9:15:68:d6:3a:bc:22:86:16:84:aa:4b:5a + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WR3 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:8f:34:75:87:af:84:72:14:8d:07:10:91:6f:03: + ac:f1:d4:08:35:9a:19:f2:9b:18:89:34:6c:98:8f: + 7a:d4:dd:ea:05:e8:de:1b:7c:8c:54:12:ba:79:8a: + fb:18:0d:0d:7c:9c:f3:bd:38:e4:a8:5e:c6:33:cb: + 46:89:6f:46:a0:e9:37:63:8d:dc:cc:d5:97:4e:32: + ad:7b:1d:23:05:b9:f5:7b:49:43:98:d0:bc:57:c7: + 53:78:18:b1:ed:a7:54:b2:7c:86:be:f0:54:45:bc: + 87:ba:99:59:1d:f4:b8:db:00:fb:81:4f:46:2b:62: + 5e:b1:3a:a5:2a:17:23:ac:a2:be:c5:8e:e5:5e:fd: + 71:1e:7d:a4:b4:23:7d:04:52:b2:34:d2:df:99:ac: + 87:c6:4c:59:5f:f8:e6:4f:8e:75:92:c2:b2:30:46: + 92:d0:b6:0d:c7:e4:89:67:ff:3f:54:94:27:65:e3: + 01:c8:4a:2c:84:2f:65:5f:cd:ad:5c:fd:a6:ad:41: + 5b:dc:4c:3f:17:96:91:7d:a9:d8:3c:53:2a:1c:d0: + e6:d4:77:e6:43:4a:c2:b7:f8:48:a2:cd:ad:63:b5: + 25:6b:96:72:1d:81:45:6f:86:69:c4:e4:e6:78:4c: + 31:e6:a1:7f:a7:01:73:0a:87:ef:87:89:72:cc:d3: + c5:8d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + C7:81:F5:FD:8E:88:D9:00:3C:4D:63:A2:50:31:24:A0:CE:23:FE:23 + X509v3 Authority Key Identifier: + keyid:E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r1.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r1.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: sha256WithRSAEncryption + 9c:8d:43:94:94:33:48:a7:16:6f:25:d7:ac:94:ac:80:a3:28: + e8:a1:bb:e1:33:2a:86:cb:93:83:ae:da:d0:55:f4:db:be:76: + f9:e8:89:6f:96:2c:38:97:3c:0d:53:87:6a:5c:29:3a:f6:ee: + 3d:d9:79:06:e0:04:80:82:b8:55:ae:e5:f6:3d:c9:f4:cd:7f: + 12:37:96:8c:64:cc:dd:1a:2c:ce:60:49:1a:ef:36:a3:3e:84: + 5a:2e:6a:ef:9c:5e:17:ea:27:26:68:76:1e:6f:7c:6b:fc:89: + 00:8f:e6:38:35:ea:e4:ba:1f:61:c4:3d:01:f7:ca:3f:d6:4c: + 66:ef:98:c1:6f:bf:a8:7a:b2:5f:62:61:68:e9:ed:be:5e:e2: + f1:2f:a5:d5:8f:02:70:a1:2a:33:53:45:2b:8b:38:10:16:0f: + 44:58:d9:0d:ac:0e:1d:7e:df:49:c8:5b:48:c5:4f:9f:93:6e: + d3:89:6b:53:ac:6e:7e:e6:6a:46:8b:04:43:0d:a8:d1:40:32: + cc:3a:32:03:9d:8d:5f:32:53:5a:bd:46:d8:55:60:ff:40:3d: + 85:da:d0:ff:a7:de:f4:6d:f5:eb:bc:ca:c4:da:97:12:bb:3a: + 32:91:ed:b4:4a:2e:19:ba:66:d9:fb:73:ae:67:2f:ae:e6:31: + 4d:fc:5c:e0:6d:86:c0:18:b7:2c:52:e8:cc:da:72:d3:8d:a0: + 0d:f5:c1:cc:3c:a7:d6:cb:5a:5a:cc:bb:f9:09:f3:32:54:79: + f4:5c:fa:8c:13:a4:e5:1e:0b:4f:e9:9a:d3:e2:a3:9d:f4:61: + 32:1e:53:da:e7:26:eb:d1:e4:bc:d4:2d:0d:99:55:6b:5b:4b: + 52:5c:ec:d3:32:c4:75:04:9e:85:30:a3:67:a4:98:b0:6b:76: + 6c:c5:4a:e9:db:ed:c7:37:32:08:fd:10:0d:41:67:35:70:b0: + 83:0d:76:fa:61:92:90:0b:a3:e0:e4:62:f2:43:11:a6:72:fc: + 50:48:e4:35:b7:70:f4:a2:f5:79:86:c4:0b:70:f4:18:fb:9e: + d9:89:36:00:68:71:92:67:1d:9b:50:68:3a:9d:39:91:8c:3f: + 36:7a:a0:87:b4:15:f0:32:b2:05:35:07:6e:31:f4:a5:79:4b: + 88:eb:12:39:8f:82:2e:1d:5e:4c:cf:83:a3:aa:d2:8e:a1:a7: + 0d:07:94:5f:29:59:98:f0:a6:ba:f7:9a:c3:7f:08:56:70:5a: + 6b:a1:22:cf:aa:67:81:9d:6e:e8:e7:8e:ff:55:33:7e:19:b2: + 4e:6d:27:d0:6f:bd:25:9d:ca:4b:63:2a:d3:c8:ac:36:05:c7: + 2e:78:65:1c:96:a9:86:91 +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIQf/AFqRVo1jq8IoYWhKpLWjANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw +MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl +cnZpY2VzMQwwCgYDVQQDEwNXUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCPNHWHr4RyFI0HEJFvA6zx1Ag1mhnymxiJNGyYj3rU3eoF6N4bfIxUErp5 +ivsYDQ18nPO9OOSoXsYzy0aJb0ag6TdjjdzM1ZdOMq17HSMFufV7SUOY0LxXx1N4 +GLHtp1SyfIa+8FRFvIe6mVkd9LjbAPuBT0YrYl6xOqUqFyOsor7FjuVe/XEefaS0 +I30EUrI00t+ZrIfGTFlf+OZPjnWSwrIwRpLQtg3H5Iln/z9UlCdl4wHISiyEL2Vf +za1c/aatQVvcTD8XlpF9qdg8Uyoc0ObUd+ZDSsK3+Eiiza1jtSVrlnIdgUVvhmnE +5OZ4TDHmoX+nAXMKh++HiXLM08WNAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBTHgfX9jojZADxNY6JQMSSgziP+IzAfBgNVHSMEGDAWgBTk +rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG +GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw +Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq +hkiG9w0BAQsFAAOCAgEAnI1DlJQzSKcWbyXXrJSsgKMo6KG74TMqhsuTg67a0FX0 +2752+eiJb5YsOJc8DVOHalwpOvbuPdl5BuAEgIK4Va7l9j3J9M1/EjeWjGTM3Ros +zmBJGu82oz6EWi5q75xeF+onJmh2Hm98a/yJAI/mODXq5LofYcQ9AffKP9ZMZu+Y +wW+/qHqyX2JhaOntvl7i8S+l1Y8CcKEqM1NFK4s4EBYPRFjZDawOHX7fSchbSMVP +n5Nu04lrU6xufuZqRosEQw2o0UAyzDoyA52NXzJTWr1G2FVg/0A9hdrQ/6fe9G31 +67zKxNqXErs6MpHttEouGbpm2ftzrmcvruYxTfxc4G2GwBi3LFLozNpy042gDfXB +zDyn1staWsy7+QnzMlR59Fz6jBOk5R4LT+ma0+KjnfRhMh5T2ucm69HkvNQtDZlV +a1tLUlzs0zLEdQSehTCjZ6SYsGt2bMVK6dvtxzcyCP0QDUFnNXCwgw12+mGSkAuj +4ORi8kMRpnL8UEjkNbdw9KL1eYbEC3D0GPue2Yk2AGhxkmcdm1BoOp05kYw/Nnqg +h7QV8DKyBTUHbjH0pXlLiOsSOY+CLh1eTM+Do6rSjqGnDQeUXylZmPCmuveaw38I +VnBaa6Eiz6pngZ1u6OeO/1UzfhmyTm0n0G+9JZ3KS2Mq08isNgXHLnhlHJaphpE= +-----END CERTIFICATE----- + +SHA-256 hash: dc9416c2f855126d6de977677538f2f967ff4998e90dfa435a17219be077fc06 +Subject: "CN=WR4, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R1, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f0:05:b4:da:75:b8:6a:5a:c6:1f:e4:30:77:13:cd + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R1 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WR4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:af:4e:51:bf:ce:50:a4:eb:8e:3d:91:a5:bf:0c: + 2a:22:aa:8a:74:a4:8c:32:68:df:0a:40:66:ec:57: + 6d:2c:af:46:f8:db:d2:6b:44:c4:0b:25:3f:fb:b0: + 84:4b:b1:77:6b:55:c0:39:ef:be:55:f5:74:3f:16: + 55:4f:52:cc:85:41:a5:87:13:18:1a:41:a7:f6:3d: + 9c:4d:56:46:1f:4f:d4:93:e7:b6:bd:51:b5:7e:35: + 39:5d:72:79:b1:be:8a:0b:9a:98:70:fd:31:6f:96: + 7a:6a:da:b3:35:e7:29:47:8a:af:25:1a:a8:10:a5: + 1f:7f:e8:02:ee:a2:59:96:0d:53:8f:14:48:00:95: + 37:7d:42:81:16:f6:02:cc:b8:6d:e5:3b:7d:65:b6: + c7:a7:65:64:f5:94:24:12:d9:14:55:4b:15:e3:ed: + c4:77:da:55:e0:48:4b:24:d5:9c:f9:ed:e4:65:80: + 27:f2:7c:0b:d4:25:4b:4c:b7:df:36:b2:83:51:d9: + dc:ce:54:e2:a3:f7:39:62:78:5a:db:75:f0:59:87: + 16:47:42:7e:c8:26:e1:9c:71:d8:89:9c:a4:d3:79: + b0:63:c4:c8:54:71:41:e4:eb:6c:a5:3b:b8:1e:2e: + d6:f7:24:c5:1b:6e:7b:d2:60:3d:94:01:c9:60:ce: + bc:25 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 9B:C8:11:BC:3D:AA:36:B9:31:8C:4E:8F:44:D5:57:32:2F:C3:C0:61 + X509v3 Authority Key Identifier: + keyid:E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r1.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r1.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: sha256WithRSAEncryption + 87:69:c3:f5:60:f9:b2:4c:d4:2c:0c:66:21:db:71:55:96:45: + f3:fe:70:b7:98:9f:20:c5:00:51:13:55:c1:97:0b:f6:eb:8e: + be:b3:53:ef:9a:55:87:2d:d8:e1:da:bd:3e:d0:43:c8:89:a0: + 4d:c2:17:ae:aa:7c:10:b9:50:1d:b3:06:47:6a:27:0b:5c:b9: + 85:18:a8:47:71:86:d4:9f:2a:18:17:b7:07:50:d0:ce:7d:2a: + a3:91:a4:af:1e:22:8a:3f:dd:ea:dc:a8:1b:17:f3:74:0b:ed: + 3d:14:3e:93:a3:da:5d:af:0b:59:d8:63:a5:2f:ff:58:58:0e: + e8:c5:ce:29:ee:aa:4e:27:15:9a:3e:b8:5d:8c:23:a0:34:18: + 36:e6:07:b4:25:8f:16:b5:bc:8a:60:9d:dd:1d:79:1f:ed:ca: + 94:29:cc:ec:5b:d0:c9:d3:6b:d3:82:cf:52:df:cb:60:cf:06: + 64:70:49:c9:4a:b5:a1:7b:c4:e5:12:96:92:8c:35:3e:d1:e9: + ba:6d:fd:f2:e1:b2:57:37:fe:be:ef:b4:d6:2f:e6:74:34:29: + b1:bf:c8:fc:f4:15:f4:10:09:8a:7f:44:d9:c7:d8:2e:50:2c: + 36:5f:55:69:4a:14:8a:0f:6a:ba:54:be:8e:49:dd:86:d3:92: + 41:c5:ad:c3:ad:98:2e:e1:a8:ff:22:3d:70:5e:14:63:8a:bd: + 95:68:0d:3b:b2:fd:21:55:47:42:8f:78:a0:2a:cb:d6:04:4c: + 28:03:6d:16:46:9c:2c:31:02:c0:0b:85:48:ab:ee:85:ae:c3: + 6a:76:3b:85:9e:d8:a8:5e:87:90:d9:49:cd:30:3a:63:d5:11: + 36:af:4c:c6:a2:61:31:e4:dd:91:e7:f3:fa:cd:40:77:f4:18: + d1:ed:8c:1c:68:1b:13:ea:0d:77:86:b0:4d:da:c4:c5:2d:81: + d8:4a:7b:c1:c4:a2:d6:80:37:e2:92:1a:26:04:2e:5a:ef:05: + ae:87:02:b3:3b:2a:73:ea:09:59:3a:f0:d9:54:20:7b:dc:60: + 51:95:0c:64:b4:56:6c:5e:23:dc:52:8f:b1:55:60:57:ee:e0: + f7:94:4d:12:31:a1:0b:53:3c:2d:ab:3c:c3:0e:53:fa:e0:4f: + 30:bb:12:42:4d:81:44:77:30:7f:20:d1:db:4f:76:24:59:5d: + 1a:e0:3c:31:40:2b:18:df:e7:1d:30:df:59:a6:0b:20:f0:94: + 87:00:61:a5:83:a3:2a:78:b8:78:f2:eb:69:da:bb:00:6d:90: + a0:65:6c:cd:9c:20:25:ea:8b:5c:90:5f:f8:8e:a7:cb:31:5d: + d9:ce:4e:5c:c1:ba:e4:d7 +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIQf/AFtNp1uGpaxh/kMHcTzTANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw +MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl +cnZpY2VzMQwwCgYDVQQDEwNXUjQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCvTlG/zlCk6449kaW/DCoiqop0pIwyaN8KQGbsV20sr0b429JrRMQLJT/7 +sIRLsXdrVcA5775V9XQ/FlVPUsyFQaWHExgaQaf2PZxNVkYfT9ST57a9UbV+NTld +cnmxvooLmphw/TFvlnpq2rM15ylHiq8lGqgQpR9/6ALuolmWDVOPFEgAlTd9QoEW +9gLMuG3lO31ltsenZWT1lCQS2RRVSxXj7cR32lXgSEsk1Zz57eRlgCfyfAvUJUtM +t982soNR2dzOVOKj9zlieFrbdfBZhxZHQn7IJuGccdiJnKTTebBjxMhUcUHk62yl +O7geLtb3JMUbbnvSYD2UAclgzrwlAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBSbyBG8Pao2uTGMTo9E1VcyL8PAYTAfBgNVHSMEGDAWgBTk +rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG +GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw +Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq +hkiG9w0BAQsFAAOCAgEAh2nD9WD5skzULAxmIdtxVZZF8/5wt5ifIMUAURNVwZcL +9uuOvrNT75pVhy3Y4dq9PtBDyImgTcIXrqp8ELlQHbMGR2onC1y5hRioR3GG1J8q +GBe3B1DQzn0qo5Gkrx4iij/d6tyoGxfzdAvtPRQ+k6PaXa8LWdhjpS//WFgO6MXO +Ke6qTicVmj64XYwjoDQYNuYHtCWPFrW8imCd3R15H+3KlCnM7FvQydNr04LPUt/L +YM8GZHBJyUq1oXvE5RKWkow1PtHpum398uGyVzf+vu+01i/mdDQpsb/I/PQV9BAJ +in9E2cfYLlAsNl9VaUoUig9qulS+jkndhtOSQcWtw62YLuGo/yI9cF4UY4q9lWgN +O7L9IVVHQo94oCrL1gRMKANtFkacLDECwAuFSKvuha7DanY7hZ7YqF6HkNlJzTA6 +Y9URNq9MxqJhMeTdkefz+s1Ad/QY0e2MHGgbE+oNd4awTdrExS2B2Ep7wcSi1oA3 +4pIaJgQuWu8FrocCszsqc+oJWTrw2VQge9xgUZUMZLRWbF4j3FKPsVVgV+7g95RN +EjGhC1M8Las8ww5T+uBPMLsSQk2BRHcwfyDR2092JFldGuA8MUArGN/nHTDfWaYL +IPCUhwBhpYOjKni4ePLradq7AG2QoGVszZwgJeqLXJBf+I6nyzFd2c5OXMG65Nc= +-----END CERTIFICATE----- + +SHA-256 hash: ae0fc852280f1b87cedaf73cfb84cf106efec88e8294253af352ed4034460d7b +Subject: "CN=WR5, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R2, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f4:e5:c9:14:96:b0:f2:a1:89:05:ed:50:1e:62:a3 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R2 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WR5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:9b:d5:5c:98:85:c1:56:ed:4b:69:4e:a3:73:22: + 2c:ba:b4:e2:64:d2:62:6e:a5:cd:1d:27:2d:4f:77: + be:96:c1:e8:32:9b:e3:d9:6d:09:1e:f0:3f:60:9d: + 81:bd:da:86:2f:c0:62:b7:0c:a4:ed:c8:5c:bc:a9: + 5d:88:c5:60:16:2a:61:0d:5f:19:57:81:4c:13:eb: + 2e:b0:19:f6:e5:db:86:59:18:9b:21:14:3d:e8:fd: + 63:16:13:b6:e8:70:25:d5:4f:95:6f:46:f0:8c:46: + be:b7:23:80:35:90:52:ec:4e:45:0b:24:16:28:6b: + 9b:2e:5c:28:73:00:02:c7:74:2a:30:76:8f:89:ee: + b5:c2:f9:d2:4d:1a:11:d3:ba:f2:72:7f:3f:6a:7b: + 42:3c:6b:bc:a5:0d:b6:b4:16:20:f1:c3:30:12:a7: + 5d:1d:02:b4:99:7f:5b:31:3a:6c:b6:d5:3e:21:a2: + bc:68:93:de:9b:9f:67:36:8b:61:77:3f:17:96:b2: + 45:8b:4e:c9:f1:26:18:c1:eb:73:b0:aa:4b:b4:d6: + 40:bf:43:f1:c1:ca:c9:74:4c:55:3b:cc:54:80:f8: + 30:33:e1:14:c7:cb:bb:05:64:aa:d1:2e:bc:7c:28: + 89:78:83:06:e9:b7:02:48:e3:8b:a1:86:b9:55:a8: + 40:dd + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 4C:5B:19:C2:8F:1A:7F:55:6F:AA:10:29:FA:02:8B:C7:3C:2A:22:3C + X509v3 Authority Key Identifier: + keyid:BB:FF:CA:8E:23:9F:4F:99:CA:DB:E2:68:A6:A5:15:27:17:1E:D9:0E + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r2.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r2.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: sha256WithRSAEncryption + c1:c0:50:db:85:d8:49:34:e5:9e:84:35:1a:42:3b:89:b6:4c: + 8a:9a:9d:9a:44:3d:d1:4a:68:04:f1:f9:0e:ae:c4:9c:33:07: + 83:3d:bc:f8:06:82:12:3c:c7:1a:0f:38:ab:86:bb:0b:1f:e0: + 5f:e4:67:23:22:a6:a9:6f:4f:3c:00:63:11:87:d0:20:d6:b6: + e1:f0:0c:56:50:ea:e8:ec:14:3e:93:c3:5a:97:30:bf:4f:1b: + d4:a9:6b:5a:dc:ae:17:50:12:3b:1b:5c:e0:81:ed:dc:8b:b1: + be:4e:04:25:79:d1:90:85:41:82:2e:eb:b0:39:4a:a2:41:f5: + b0:70:a1:26:7b:0f:14:7e:03:ce:d5:46:dd:69:d5:38:5b:a3: + cb:a4:ad:48:43:1a:11:75:b1:8a:a7:f3:53:ee:14:e1:84:e0: + 7d:3a:e4:55:ec:59:18:74:5b:99:75:3e:4b:91:62:e9:53:f0: + 18:5b:cd:44:09:3c:82:8c:5c:bf:3a:c6:7a:87:c0:04:0a:4a: + a5:4d:43:aa:5f:9e:a8:b4:68:6c:90:07:51:ee:74:d1:57:d5: + 55:62:e2:7a:bd:8c:46:8c:4a:1e:7f:b2:ac:3b:77:14:6e:80: + 25:63:0f:92:e4:72:08:99:2e:7f:0a:02:39:0d:97:14:0c:92: + 68:c8:78:45:00:31:75:61:59:a9:51:a9:aa:8b:3b:37:ab:4c: + 76:f5:4f:cf:b4:ec:d3:87:18:54:13:ab:84:76:0e:74:5d:ba: + c8:80:c6:6f:f6:dc:8f:ba:50:7a:e8:51:81:8a:7e:b2:a6:6a: + fb:43:e8:3f:71:43:6f:07:3e:07:b5:96:d0:c0:6b:b0:a2:af: + 72:b5:7d:ca:0c:e4:47:c6:31:92:d0:3e:1a:6d:d4:25:3c:9c: + 17:45:1b:b3:81:c4:26:fe:a7:1c:16:b2:d0:80:c6:7c:b4:70: + 53:99:01:75:66:84:6e:63:f6:4c:4b:ca:1b:f3:a0:c6:37:09: + 6f:e8:44:a1:52:9d:fa:cb:3a:6e:e2:d7:d5:d7:bf:0e:f5:8c: + 76:31:4f:e5:ad:bb:3d:c0:93:de:0c:75:51:4d:37:76:31:19: + ff:b8:c5:9d:19:f0:39:e3:47:0a:d4:59:4d:79:19:dd:05:07: + 5b:1a:da:3b:d8:ad:e3:6d:06:f7:4d:46:be:8b:37:71:16:de: + 39:b0:94:b5:cb:a5:f7:f5:1b:f4:28:a5:a8:2d:fe:7d:84:be: + a5:0b:bc:ed:83:fc:62:60:a3:ce:86:26:fe:4d:12:c2:d7:e2: + 1c:95:c1:ae:de:6c:7a:05:a4:2b:30:f8:d0:de:46:f7:59:5f: + b6:77:b8:4f:5e:8f:ab:0b +-----BEGIN CERTIFICATE----- +MIIFCzCCAvOgAwIBAgIQf/TlyRSWsPKhiQXtUB5iozANBgkqhkiG9w0BAQsFADBH +MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM +QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw +MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl +cnZpY2VzMQwwCgYDVQQDEwNXUjUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCb1VyYhcFW7UtpTqNzIiy6tOJk0mJupc0dJy1Pd76Wwegym+PZbQke8D9g +nYG92oYvwGK3DKTtyFy8qV2IxWAWKmENXxlXgUwT6y6wGfbl24ZZGJshFD3o/WMW +E7bocCXVT5VvRvCMRr63I4A1kFLsTkULJBYoa5suXChzAALHdCowdo+J7rXC+dJN +GhHTuvJyfz9qe0I8a7ylDba0FiDxwzASp10dArSZf1sxOmy21T4horxok96bn2c2 +i2F3PxeWskWLTsnxJhjB63Owqku01kC/Q/HBysl0TFU7zFSA+DAz4RTHy7sFZKrR +Lrx8KIl4gwbptwJI44uhhrlVqEDdAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG +MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/ +AgEAMB0GA1UdDgQWBBRMWxnCjxp/VW+qECn6AovHPCoiPDAfBgNVHSMEGDAWgBS7 +/8qOI59Pmcrb4mimpRUnFx7ZDjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG +GGh0dHA6Ly9pLnBraS5nb29nL3IyLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw +Oi8vYy5wa2kuZ29vZy9yL3IyLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq +hkiG9w0BAQsFAAOCAgEAwcBQ24XYSTTlnoQ1GkI7ibZMipqdmkQ90UpoBPH5Dq7E +nDMHgz28+AaCEjzHGg84q4a7Cx/gX+RnIyKmqW9PPABjEYfQINa24fAMVlDq6OwU +PpPDWpcwv08b1KlrWtyuF1ASOxtc4IHt3Iuxvk4EJXnRkIVBgi7rsDlKokH1sHCh +JnsPFH4DztVG3WnVOFujy6StSEMaEXWxiqfzU+4U4YTgfTrkVexZGHRbmXU+S5Fi +6VPwGFvNRAk8goxcvzrGeofABApKpU1Dql+eqLRobJAHUe500VfVVWLier2MRoxK +Hn+yrDt3FG6AJWMPkuRyCJkufwoCOQ2XFAySaMh4RQAxdWFZqVGpqos7N6tMdvVP +z7Ts04cYVBOrhHYOdF26yIDGb/bcj7pQeuhRgYp+sqZq+0PoP3FDbwc+B7WW0MBr +sKKvcrV9ygzkR8YxktA+Gm3UJTycF0Ubs4HEJv6nHBay0IDGfLRwU5kBdWaEbmP2 +TEvKG/OgxjcJb+hEoVKd+ss6buLX1de/DvWMdjFP5a27PcCT3gx1UU03djEZ/7jF +nRnwOeNHCtRZTXkZ3QUHWxraO9it420G901Gvos3cRbeObCUtcul9/Ub9CilqC3+ +fYS+pQu87YP8YmCjzoYm/k0SwtfiHJXBrt5segWkKzD40N5G91lftne4T16Pqws= +-----END CERTIFICATE----- + +SHA-256 hash: 1dfc1605fbad358d8bc844f76d15203fac9ca5c1a79fd4857ffaf2864fbebf96 +Subject: "CN=WE1, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R4, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f3:19:77:97:2c:22:4a:76:15:5d:13:b6:d6:85:e3 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WE1 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:6f:cd:3a:fe:67:57:47:4c:21:03:85:40:c2:47: + 5d:bb:58:47:0f:40:c1:5c:17:85:c6:19:37:e7:d5: + 7c:ed:86:4b:9b:81:d9:d7:1a:13:a5:0a:03:f8:98: + c4:c6:e8:9e:ff:10:59:8f:2c:26:98:f5:e6:26:25: + bb:0f:02:fa:56 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 90:77:92:35:67:C4:FF:A8:CC:A9:E6:7B:D9:80:79:7B:CC:93:F9:38 + X509v3 Authority Key Identifier: + keyid:80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r4.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r4.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:e7:02:ab:51:d6:f7:43:95:ce:75:fe:d1:11: + 94:d5:cc:40:41:7a:26:be:d8:0c:f3:32:2d:3d:90:ae:15:0f: + 23:48:12:52:8f:3e:64:79:13:af:f5:a6:2c:02:6e:55:b1:02: + 30:26:89:cc:68:01:62:e7:89:ab:7e:17:e8:14:d6:44:7e:e3: + 4c:49:0e:bf:6c:80:62:34:b8:b2:a1:7e:3a:16:88:50:bc:a7: + 88:a0:9f:7d:73:1e:ec:52:41:4d:ee:e2:56 +-----BEGIN CERTIFICATE----- +MIICnzCCAiWgAwIBAgIQf/MZd5csIkp2FV0TttaF4zAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNXRTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARvzTr+ +Z1dHTCEDhUDCR127WEcPQMFcF4XGGTfn1XzthkubgdnXGhOlCgP4mMTG6J7/EFmP +LCaY9eYmJbsPAvpWo4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU +kHeSNWfE/6jMqeZ72YB5e8yT+TgwHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F +avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku +Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv +ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaAAwZQIx +AOcCq1HW90OVznX+0RGU1cxAQXomvtgM8zItPZCuFQ8jSBJSjz5keROv9aYsAm5V +sQIwJonMaAFi54mrfhfoFNZEfuNMSQ6/bIBiNLiyoX46FohQvKeIoJ99cx7sUkFN +7uJW +-----END CERTIFICATE----- + +SHA-256 hash: 9c3f2fd11c57d7c649ad5a0932c0f0d29756f6a0a1c74c43e1e89a62d64cd320 +Subject: "CN=WE2, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R4, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f3:2d:6b:40:9d:15:d5:96:5b:05:87:3a:7c:72:e0 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WE2 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:35:7e:1f:f2:14:ed:90:7d:e1:9e:2a:34:43:86: + c1:d5:96:e8:27:70:df:9e:04:cb:a9:ca:86:79:0b: + 08:4d:46:8a:c2:74:a4:bb:d9:bf:ee:fd:23:d7:38: + f3:4b:ef:54:17:e1:be:e7:ca:55:25:a8:0c:30:ac: + 2d:5d:4e:a1:51 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 75:BE:C4:77:AE:89:F6:44:37:7D:CF:B1:68:1F:1D:1A:EB:DC:34:59 + X509v3 Authority Key Identifier: + keyid:80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r4.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r4.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:0b:bd:b8:36:55:c8:35:a3:d2:d9:7d:39:73:d3: + f7:f7:82:b8:09:d1:81:6f:e5:64:45:db:de:aa:c0:0e:45:12: + 8f:ac:93:e8:1f:60:ec:2e:7e:44:2c:22:94:91:ec:ac:02:30: + 2f:df:0c:90:76:4c:2d:69:61:d5:4f:fd:98:98:18:84:db:34: + ea:98:ec:9b:cd:88:62:ff:d2:65:e5:33:6a:9a:0c:ed:23:49: + 38:2f:51:bf:91:d0:12:a2:c9:38:38:da +-----BEGIN CERTIFICATE----- +MIICnjCCAiWgAwIBAgIQf/Mta0CdFdWWWwWHOnxy4DAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNXRTIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQ1fh/y +FO2QfeGeKjRDhsHVlugncN+eBMupyoZ5CwhNRorCdKS72b/u/SPXOPNL71QX4b7n +ylUlqAwwrC1dTqFRo4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU +db7Ed66J9kQ3fc+xaB8dGuvcNFkwHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F +avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku +Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv +ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDZwAwZAIw +C724NlXINaPS2X05c9P394K4CdGBb+VkRdveqsAORRKPrJPoH2DsLn5ELCKUkeys +AjAv3wyQdkwtaWHVT/2YmBiE2zTqmOybzYhi/9Jl5TNqmgztI0k4L1G/kdASosk4 +ONo= +-----END CERTIFICATE----- + +SHA-256 hash: 9f819a4c876e12dc84e6fe0e37c1a69b137094b453fa98449398f4b71f4d0092 +Subject: "CN=WE3, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R4, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f3:2d:6d:bd:5e:dd:54:ca:4e:4b:67:95:72:91:43 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WE3 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:8c:72:71:5c:66:e5:04:54:96:79:1b:c1:c2:81: + 65:90:33:36:73:3c:c0:2f:b4:b9:54:06:2a:5a:34: + 27:95:91:35:09:aa:7a:bf:92:c9:8d:18:e8:56:92: + e2:4f:aa:6d:67:5a:6d:41:51:ac:0a:c3:75:c6:27: + b2:02:b7:c5:42 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 36:B6:2C:CE:A3:B4:D0:40:90:45:F3:8B:45:81:C1:C8:E3:19:D4:6D + X509v3 Authority Key Identifier: + keyid:80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r4.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r4.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:31:00:82:6e:b7:32:b8:68:ec:a0:2b:98:c9:b4:5c: + cd:ad:70:5f:6c:c2:75:be:32:51:19:77:d3:d0:6e:18:ed:98: + 61:1a:c2:bc:f2:ce:a1:54:a0:42:35:99:cf:8f:3b:0c:db:02: + 30:43:ed:68:35:0d:4e:55:2d:ee:e5:0f:aa:a6:93:ac:6b:cf: + 1f:ef:3c:36:61:95:2e:33:37:27:3e:52:f7:a5:d8:30:40:e8: + b7:08:4f:0f:61:6a:26:fe:eb:0d:76:3f:ae +-----BEGIN CERTIFICATE----- +MIICnzCCAiWgAwIBAgIQf/Mtbb1e3VTKTktnlXKRQzAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNXRTMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASMcnFc +ZuUEVJZ5G8HCgWWQMzZzPMAvtLlUBipaNCeVkTUJqnq/ksmNGOhWkuJPqm1nWm1B +UawKw3XGJ7ICt8VCo4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU +NrYszqO00ECQRfOLRYHByOMZ1G0wHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F +avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku +Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv +ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaAAwZQIx +AIJutzK4aOygK5jJtFzNrXBfbMJ1vjJRGXfT0G4Y7ZhhGsK88s6hVKBCNZnPjzsM +2wIwQ+1oNQ1OVS3u5Q+qppOsa88f7zw2YZUuMzcnPlL3pdgwQOi3CE8PYWom/usN +dj+u +-----END CERTIFICATE----- + +SHA-256 hash: d0c97e56c7b0ba812d944ad771f7799b5d4144a2327a4e416554f7ee2aa0aeae +Subject: "CN=WE4, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R4, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f3:2d:70:bb:d1:a7:30:9b:57:32:50:0a:c9:9a:ae + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WE4 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:c1:aa:09:fd:3c:dc:18:36:3e:db:eb:69:ad:7f: + 75:72:47:a1:c8:6c:2c:fd:28:bb:f5:60:51:77:c1: + ab:bc:ec:d2:21:f6:35:d2:5e:70:24:59:dd:fc:5b: + 13:39:3d:d1:5f:3b:d0:fb:cc:90:1d:6a:97:ff:a8: + f4:85:53:10:6c + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 6D:E7:D4:65:B4:38:57:56:95:CD:E5:B4:77:5A:36:0A:DE:7D:52:A6 + X509v3 Authority Key Identifier: + keyid:80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r4.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r4.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:64:02:30:37:cf:34:3e:33:c6:94:ca:07:f0:53:56:53:93: + c1:e5:bf:e5:69:a6:6a:47:01:b9:03:4b:08:b2:43:8c:ce:1c: + f3:6d:d8:b7:d1:85:24:09:e1:45:4d:f3:3d:15:42:94:02:30: + 46:76:60:39:6b:87:f8:09:da:d1:e9:71:40:91:b7:ee:51:7f: + d7:97:b7:78:e6:a1:aa:1d:98:3b:82:88:3a:2c:8e:7e:8c:34: + 35:71:dd:05:31:d3:ba:3f:59:0a:f2:5d +-----BEGIN CERTIFICATE----- +MIICnjCCAiWgAwIBAgIQf/MtcLvRpzCbVzJQCsmarjAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNXRTQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATBqgn9 +PNwYNj7b62mtf3VyR6HIbCz9KLv1YFF3wau87NIh9jXSXnAkWd38WxM5PdFfO9D7 +zJAdapf/qPSFUxBso4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU +befUZbQ4V1aVzeW0d1o2Ct59UqYwHwYDVR0jBBgwFoAUgEzW63T/STaj1dj8tT7F +avCUHYwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku +Z29vZy9yNC5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv +ci9yNC5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDZwAwZAIw +N880PjPGlMoH8FNWU5PB5b/laaZqRwG5A0sIskOMzhzzbdi30YUkCeFFTfM9FUKU +AjBGdmA5a4f4CdrR6XFAkbfuUX/Xl7d45qGqHZg7gog6LI5+jDQ1cd0FMdO6P1kK +8l0= +-----END CERTIFICATE----- + +SHA-256 hash: 847409e63526f162753ac49f75218efaafa7d5c94ade9095ce72e7f6b6e3ac99 +Subject: "CN=WE5, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R3, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f4:e5:cb:ec:d9:81:f2:ad:fa:08:91:3c:ef:ab:14 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R3 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=WE5 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:88:0c:8d:e1:3a:e4:24:06:93:85:77:d6:1c:c0: + ec:1f:50:df:16:08:a4:90:a5:0e:3c:ca:ee:dc:e8: + 24:ed:0b:f3:83:88:3b:ae:75:eb:b7:e6:6f:1e:3b: + 4f:20:12:2b:b7:ec:b8:1e:ab:37:d7:fb:b5:ab:7e: + c7:5b:19:fe:a2 + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + D4:65:CB:38:C7:25:3C:28:6B:E9:7E:43:C3:A1:A1:B8:E4:4C:68:A0 + X509v3 Authority Key Identifier: + keyid:C1:F1:26:BA:A0:2D:AE:85:81:CF:D3:F1:2A:12:BD:B8:0A:67:FD:BC + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r3.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r3.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:65:02:30:42:38:89:c6:9e:b1:7a:6c:18:53:ae:87:ea:5f: + 46:98:f2:7f:35:7a:84:96:aa:79:03:34:f3:d2:f8:e2:8d:1c: + e9:c2:fa:13:a3:4e:ae:7a:f1:41:b3:e8:a9:e6:ff:c6:02:31: + 00:b0:9d:15:48:1a:6f:a8:25:08:ea:cb:40:18:ea:0e:5d:5d: + a1:af:d1:79:0e:8f:5d:e4:70:30:35:8f:9c:24:8a:1f:16:00: + 9b:5a:12:21:c1:12:fd:51:34:c5:c5:e5:74 +-----BEGIN CERTIFICATE----- +MIICnzCCAiWgAwIBAgIQf/Tly+zZgfKt+giRPO+rFDAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNXRTUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASIDI3h +OuQkBpOFd9YcwOwfUN8WCKSQpQ48yu7c6CTtC/ODiDuudeu35m8eO08gEiu37Lge +qzfX+7WrfsdbGf6io4H+MIH7MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggr +BgEFBQcDAQYIKwYBBQUHAwIwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU +1GXLOMclPChr6X5Dw6GhuORMaKAwHwYDVR0jBBgwFoAUwfEmuqAtroWBz9PxKhK9 +uApn/bwwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzAChhhodHRwOi8vaS5wa2ku +Z29vZy9yMy5jcnQwKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2MucGtpLmdvb2cv +ci9yMy5jcmwwEwYDVR0gBAwwCjAIBgZngQwBAgEwCgYIKoZIzj0EAwMDaAAwZQIw +QjiJxp6xemwYU66H6l9GmPJ/NXqElqp5AzTz0vjijRzpwvoTo06uevFBs+ip5v/G +AjEAsJ0VSBpvqCUI6stAGOoOXV2hr9F5Do9d5HAwNY+cJIofFgCbWhIhwRL9UTTF +xeV0 +-----END CERTIFICATE----- + +SHA-256 hash: 812c212e9e45dc5005c7f47411183f5fb2ff1baee184d3354b2e93d78c280164 +Subject: "CN=AE1, O=Google Trust Services, C=US" +Issuer: "CN=GTS Root R4, O=Google Trust Services LLC, C=US" +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 7f:f4:e5:ce:36:a6:a1:fa:5e:e1:91:6c:08:d3:9b:7c + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Google Trust Services LLC, CN=GTS Root R4 + Validity + Not Before: Dec 13 09:00:00 2023 GMT + Not After : Feb 20 14:00:00 2029 GMT + Subject: C=US, O=Google Trust Services, CN=AE1 + Subject Public Key Info: + Public Key Algorithm: id-ecPublicKey + Public-Key: (256 bit) + pub: + 04:7d:0a:5c:db:19:c0:d9:0c:d2:79:bf:e2:68:fc: + 45:e2:17:fa:be:4d:59:1b:89:1d:ca:c0:39:6f:8c: + ed:c0:47:a1:2f:88:2b:f5:cc:34:86:f5:9b:51:8d: + 0c:30:57:f1:d8:01:64:db:94:60:b9:e0:56:a3:8b: + e6:49:80:6a:aa + ASN1 OID: prime256v1 + NIST CURVE: P-256 + X509v3 extensions: + X509v3 Key Usage: critical + Digital Signature, Certificate Sign, CRL Sign + X509v3 Extended Key Usage: + TLS Web Server Authentication + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Subject Key Identifier: + 48:89:60:F9:A3:7D:0C:EA:00:24:A2:DC:9F:07:CE:46:88:A8:32:3A + X509v3 Authority Key Identifier: + keyid:80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C + + Authority Information Access: + CA Issuers - URI:http://i.pki.goog/r4.crt + + X509v3 CRL Distribution Points: + + Full Name: + URI:http://c.pki.goog/r/r4.crl + + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.1 + + Signature Algorithm: ecdsa-with-SHA384 + 30:66:02:31:00:99:d3:28:77:7e:39:f3:e9:c1:1c:33:60:f0: + a3:43:6f:10:4a:db:b8:28:e5:43:e7:8d:16:e0:97:f4:30:78: + e0:20:5c:70:3c:84:5c:e8:09:83:29:f1:09:52:ce:3c:2b:02: + 31:00:f9:57:f6:d0:41:e5:28:16:27:3f:58:41:4b:3d:75:08: + 86:75:31:35:da:cd:5f:b0:10:bd:44:a7:8e:56:0d:1d:7f:3d: + bd:fe:43:32:db:be:2b:a3:91:ab:64:dc:c3:1e +-----BEGIN CERTIFICATE----- +MIICljCCAhugAwIBAgIQf/Tlzjamofpe4ZFsCNObfDAKBggqhkjOPQQDAzBHMQsw +CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU +MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIwMTQw +MDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp +Y2VzMQwwCgYDVQQDEwNBRTEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR9Clzb +GcDZDNJ5v+Jo/EXiF/q+TVkbiR3KwDlvjO3AR6EviCv1zDSG9ZtRjQwwV/HYAWTb +lGC54Faji+ZJgGqqo4H0MIHxMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggr +BgEFBQcDATASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRIiWD5o30M6gAk +otyfB85GiKgyOjAfBgNVHSMEGDAWgBSATNbrdP9JNqPV2Py1PsVq8JQdjDA0Bggr +BgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKGGGh0dHA6Ly9pLnBraS5nb29nL3I0LmNy +dDArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vYy5wa2kuZ29vZy9yL3I0LmNybDAT +BgNVHSAEDDAKMAgGBmeBDAECATAKBggqhkjOPQQDAwNpADBmAjEAmdMod3458+nB +HDNg8KNDbxBK27go5UPnjRbgl/QweOAgXHA8hFzoCYMp8QlSzjwrAjEA+Vf20EHl +KBYnP1hBSz11CIZ1MTXazV+wEL1Ep45WDR1/Pb3+QzLbviujkatk3MMe +-----END CERTIFICATE-----
diff --git a/net/data/ssl/chrome_root_store/root_store.md b/net/data/ssl/chrome_root_store/root_store.md index 83a99a2..45592b2 100644 --- a/net/data/ssl/chrome_root_store/root_store.md +++ b/net/data/ssl/chrome_root_store/root_store.md
@@ -1,7 +1,7 @@ <!-- mdformat off(generated) --> <!-- mdlint off(generated) --> # Chrome Root Store -Version: 19 +Version: 20 [TOC]
diff --git a/net/data/ssl/chrome_root_store/root_store.textproto b/net/data/ssl/chrome_root_store/root_store.textproto index 3ff97fa..ea1a26a7 100644 --- a/net/data/ssl/chrome_root_store/root_store.textproto +++ b/net/data/ssl/chrome_root_store/root_store.textproto
@@ -8,7 +8,7 @@ # Version # should always be incremented up whenever this (or any pem file that # it references) is changed. -version_major: 19 +version_major: 20 # CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, L=Milan, C=IT # https://ssltest-a.actalis.it:8443 @@ -381,16 +381,19 @@ # CN=GTS Root R3, O=Google Trust Services LLC, C=US trust_anchors { sha256_hex: "34d8a73ee208d9bcdb0d956520934b4e40e69482596e8b6f73c8426b010a6f48" + trust_anchor_id: "11129.9.3" } # CN=GTS Root R1, O=Google Trust Services LLC, C=US trust_anchors { sha256_hex: "d947432abde7b7fa90fc2e6b59101b1280e0e1c7e4e40fa3c6887fff57a7f4cf" + trust_anchor_id: "11129.9.1" } # CN=GTS Root R4, O=Google Trust Services LLC, C=US trust_anchors { sha256_hex: "349dfa4058c5e263123b398ae795573c4e1313c83fe68f93556cd5e8031b3c7d" + trust_anchor_id: "11129.9.4" } # CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R4 @@ -401,6 +404,7 @@ # CN=GTS Root R2, O=Google Trust Services LLC, C=US trust_anchors { sha256_hex: "8d25cd97229dbf70356bda4eb3cc734031e24cf00fafcfd32dc76eb5841c7ea8" + trust_anchor_id: "11129.9.2" } # CN=Hongkong Post Root CA 3, O=Hongkong Post, L=Hong Kong, ST=Hong Kong, C=HK @@ -1471,3 +1475,102 @@ sha256_hex: "fe95a24e7f94978e58d99350ab7ab789774a987cd25187c128c191d207523bb1" eutl: true } + +# "CN=WR1, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "b10b6f00e609509e8700f6d34687a2bfce38ea05a8fdf1cdc40c3a2a0d0d0e45" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.5" +} + +# "CN=WR2, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "e6fe22bf45e4f0d3b85c59e02c0f495418e1eb8d3210f788d48cd5e1cb547cd4" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.6" +} + +# "CN=WR3, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "2fe357db13751ff9160e87354975b3407498f41c9bd16a48657866e6e5a9b4c7" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.7" +} + +# "CN=WR4, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "dc9416c2f855126d6de977677538f2f967ff4998e90dfa435a17219be077fc06" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.8" +} + +# "CN=WR5, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "ae0fc852280f1b87cedaf73cfb84cf106efec88e8294253af352ed4034460d7b" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.9" +} + +# "CN=WE1, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "1dfc1605fbad358d8bc844f76d15203fac9ca5c1a79fd4857ffaf2864fbebf96" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.10" +} + +# "CN=WE2, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "9c3f2fd11c57d7c649ad5a0932c0f0d29756f6a0a1c74c43e1e89a62d64cd320" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.11" +} + +# "CN=WE3, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "9f819a4c876e12dc84e6fe0e37c1a69b137094b453fa98449398f4b71f4d0092" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.12" +} + +# "CN=WE4, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "d0c97e56c7b0ba812d944ad771f7799b5d4144a2327a4e416554f7ee2aa0aeae" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.13" +} + +# "CN=WE5, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "847409e63526f162753ac49f75218efaafa7d5c94ade9095ce72e7f6b6e3ac99" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.14" +} + +# "CN=AE1, O=Google Trust Services, C=US" +additional_certs { + sha256_hex: "812c212e9e45dc5005c7f47411183f5fb2ff1baee184d3354b2e93d78c280164" + enforce_anchor_constraints: true + enforce_anchor_expiry: true + tls_trust_anchor: true + trust_anchor_id: "11129.9.15" +}
diff --git a/net/device_bound_sessions/mock_session_store.h b/net/device_bound_sessions/mock_session_store.h index 76caa8b..dc2888d 100644 --- a/net/device_bound_sessions/mock_session_store.h +++ b/net/device_bound_sessions/mock_session_store.h
@@ -26,10 +26,7 @@ SaveSession, (const SchemefulSite& site, const Session& session), (override)); - MOCK_METHOD(void, - DeleteSession, - (const SchemefulSite& site, const Session::Id& session_id), - (override)); + MOCK_METHOD(void, DeleteSession, (const SessionKey& key), (override)); MOCK_METHOD(SessionStore::SessionsMap, GetAllSessions, (), (const, override)); MOCK_METHOD(void, RestoreSessionBindingKey,
diff --git a/net/device_bound_sessions/session_service_impl.cc b/net/device_bound_sessions/session_service_impl.cc index 3c30d14..35f3e7f 100644 --- a/net/device_bound_sessions/session_service_impl.cc +++ b/net/device_bound_sessions/session_service_impl.cc
@@ -184,8 +184,12 @@ std::ranges::subrange<SessionServiceImpl::SessionsMap::iterator> SessionServiceImpl::GetSessionsForSite(const SchemefulSite& site) { const auto now = base::Time::Now(); - auto [begin, end] = unpartitioned_sessions_.equal_range(site); - for (auto it = begin; it != end;) { + // Session keys are sorted by site, then identifier. So the first + // element not less than (`site`, "") is the first session for this + // site. + auto it = + unpartitioned_sessions_.lower_bound(SessionKey{site, Session::Id("")}); + while (it != unpartitioned_sessions_.end() && it->first.site == site) { auto curit = it; ++it; @@ -198,9 +202,9 @@ } } - auto sessions_for_site = unpartitioned_sessions_.equal_range(site); - return std::ranges::subrange<SessionsMap::iterator>(sessions_for_site.first, - sessions_for_site.second); + return std::ranges::subrange<SessionsMap::iterator>( + unpartitioned_sessions_.lower_bound(SessionKey{site, Session::Id("")}), + it); } std::optional<SessionService::DeferralParams> SessionServiceImpl::ShouldDefer( @@ -373,11 +377,8 @@ // `queued_operations_`, which is owned by `this`. base::Unretained(this), std::move(callback))); } else { - std::vector<SessionKey> sessions = - base::ToVector(unpartitioned_sessions_, [](const auto& pair) { - const auto& [site, session] = pair; - return SessionKey(site, session->id()); - }); + std::vector<SessionKey> sessions = base::ToVector( + unpartitioned_sessions_, [](const auto& pair) { return pair.first; }); base::SequencedTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), std::move(sessions))); } @@ -387,26 +388,20 @@ const SchemefulSite& site, const Session::Id& id, SessionService::OnAccessCallback per_request_callback) { - auto range = unpartitioned_sessions_.equal_range(site); - for (auto it = range.first; it != range.second; ++it) { - if (it->second->id() == id) { - DeleteSessionAndNotifyInternal(it, per_request_callback); - return; - } + auto it = unpartitioned_sessions_.find(SessionKey{site, id}); + if (it == unpartitioned_sessions_.end()) { + return; } + + DeleteSessionAndNotifyInternal(it, per_request_callback); } Session* SessionServiceImpl::GetSession(const SchemefulSite& site, const Session::Id& session_id) const { - // Intentionally do not use `GetSessionsForSite` here so we do not - // modify the session during testing. - auto range = unpartitioned_sessions_.equal_range(site); - for (auto it = range.first; it != range.second; ++it) { - if (it->second->id() == session_id) { - return it->second.get(); - } + auto it = unpartitioned_sessions_.find(SessionKey{site, session_id}); + if (it != unpartitioned_sessions_.end()) { + return it->second.get(); } - return nullptr; } @@ -415,8 +410,9 @@ if (session_store_) { session_store_->SaveSession(site, *session); } - // TODO(crbug.com/402020386): Enforce unique session ids per site. - unpartitioned_sessions_.emplace(site, std::move(session)); + + unpartitioned_sessions_.emplace(SessionKey{site, session->id()}, + std::move(session)); } void SessionServiceImpl::DeleteAllSessions( @@ -430,8 +426,9 @@ auto curit = it; ++it; - if (SessionMatchesFilter(curit->first, *curit->second, created_after_time, - created_before_time, origin_and_site_matcher)) { + if (SessionMatchesFilter(curit->first.site, *curit->second, + created_after_time, created_before_time, + origin_and_site_matcher)) { DeleteSessionAndNotifyInternal(curit, base::NullCallback()); } } @@ -454,11 +451,11 @@ SessionServiceImpl::SessionsMap::iterator it, SessionService::OnAccessCallback per_request_callback) { if (session_store_) { - session_store_->DeleteSession(it->first, it->second->id()); + session_store_->DeleteSession(it->first); } NotifySessionAccess(per_request_callback, - SessionAccess::AccessType::kTermination, it->first, + SessionAccess::AccessType::kTermination, it->first.site, *it->second); unpartitioned_sessions_.erase(it);
diff --git a/net/device_bound_sessions/session_service_impl.h b/net/device_bound_sessions/session_service_impl.h index 99bf7edc..cf7ba442 100644 --- a/net/device_bound_sessions/session_service_impl.h +++ b/net/device_bound_sessions/session_service_impl.h
@@ -106,8 +106,9 @@ private: friend class SessionServiceImplWithStoreTest; - // The key is the site (eTLD+1) of the session's origin. - using SessionsMap = std::multimap<SchemefulSite, std::unique_ptr<Session>>; + // The key is the site (eTLD+1) of the session's origin and the + // session id. + using SessionsMap = std::map<SessionKey, std::unique_ptr<Session>>; using DeferredRequestsMap = std::unordered_map<Session::Id, absl::InlinedVector<DeferredURLRequest, 1>>;
diff --git a/net/device_bound_sessions/session_service_impl_unittest.cc b/net/device_bound_sessions/session_service_impl_unittest.cc index 2b76599..414835e 100644 --- a/net/device_bound_sessions/session_service_impl_unittest.cc +++ b/net/device_bound_sessions/session_service_impl_unittest.cc
@@ -1085,7 +1085,8 @@ // Complete loading. If we did not defer, we'd miss this session. SessionStore::SessionsMap session_map; - session_map.insert({SchemefulSite(kTestUrl), std::move(session)}); + session_map.insert( + {SessionKey{SchemefulSite(kTestUrl), session->id()}, std::move(session)}); FinishLoadingSessions(std::move(session_map)); // But we did defer, so we found it. @@ -1157,7 +1158,8 @@ ASSERT_TRUE(session); SessionStore::SessionsMap session_map; - session_map.insert({SchemefulSite(kTestUrl), std::move(session)}); + session_map.insert( + {SessionKey{SchemefulSite(kTestUrl), session->id()}, std::move(session)}); FinishLoadingSessions(std::move(session_map)); // Create a request that should be deferred due to the session @@ -1176,7 +1178,7 @@ // Now actually defer the request auto scoped_test_fetcher = ScopedTestRegistrationFetcher::CreateWithSuccess( kSessionId, kUrlString, kOrigin); - EXPECT_CALL(store(), DeleteSession(_, _)).Times(1); + EXPECT_CALL(store(), DeleteSession(_)).Times(1); EXPECT_CALL(store(), SaveSession(_, _)).Times(1); EXPECT_CALL(store(), RestoreSessionBindingKey(SchemefulSite(kTestUrl), Session::Id(kSessionId), _))
diff --git a/net/device_bound_sessions/session_store.h b/net/device_bound_sessions/session_store.h index 9688a57..56efd95 100644 --- a/net/device_bound_sessions/session_store.h +++ b/net/device_bound_sessions/session_store.h
@@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "net/device_bound_sessions/session.h" +#include "net/device_bound_sessions/session_key.h" namespace base { class FilePath; @@ -34,15 +35,14 @@ SessionStore(const SessionStore&) = delete; SessionStore& operator=(const SessionStore&) = delete; - using SessionsMap = std::multimap<SchemefulSite, std::unique_ptr<Session>>; + using SessionsMap = std::map<SessionKey, std::unique_ptr<Session>>; using LoadSessionsCallback = base::OnceCallback<void(SessionsMap)>; virtual void LoadSessions(LoadSessionsCallback callback) = 0; virtual void SaveSession(const SchemefulSite& site, const Session& session) = 0; - virtual void DeleteSession(const SchemefulSite& site, - const Session::Id& session_id) = 0; + virtual void DeleteSession(const SessionKey& key) = 0; // Returns session objects created from currently cached store data. virtual SessionsMap GetAllSessions() const = 0;
diff --git a/net/device_bound_sessions/session_store_impl.cc b/net/device_bound_sessions/session_store_impl.cc index 766af01..dfe5786 100644 --- a/net/device_bound_sessions/session_store_impl.cc +++ b/net/device_bound_sessions/session_store_impl.cc
@@ -174,7 +174,8 @@ } // Restored session entry has passed basic validation checks. Save it. - site_sessions.emplace(site, std::move(session)); + site_sessions.emplace(SessionKey{site, session->id()}, + std::move(session)); } // Remove the entire site entry from the DB if a single invalid session is @@ -226,19 +227,18 @@ session_data_->UpdateData(site_str, site_proto); } -void SessionStoreImpl::DeleteSession(const SchemefulSite& site, - const Session::Id& session_id) { +void SessionStoreImpl::DeleteSession(const SessionKey& key) { if (db_status_ != DBStatus::kSuccess) { return; } proto::SiteSessions site_proto; - std::string site_str = site.Serialize(); + std::string site_str = key.site.Serialize(); if (!session_data_->TryGetData(site_str, &site_proto)) { return; } - if (site_proto.sessions().count(*session_id) == 0) { + if (site_proto.sessions().count(*key.id) == 0) { return; } @@ -249,10 +249,10 @@ return; } - site_proto.mutable_sessions()->erase(*session_id); + site_proto.mutable_sessions()->erase(*key.id); // Schedule a DB update for the site entry. - session_data_->UpdateData(site.Serialize(), site_proto); + session_data_->UpdateData(key.site.Serialize(), site_proto); } SessionStore::SessionsMap SessionStoreImpl::GetAllSessions() const {
diff --git a/net/device_bound_sessions/session_store_impl.h b/net/device_bound_sessions/session_store_impl.h index 5ed1df0..92bf9a8 100644 --- a/net/device_bound_sessions/session_store_impl.h +++ b/net/device_bound_sessions/session_store_impl.h
@@ -59,8 +59,7 @@ // SessionStore implementation: void LoadSessions(LoadSessionsCallback callback) override; void SaveSession(const SchemefulSite& site, const Session& session) override; - void DeleteSession(const SchemefulSite& site, - const Session::Id& session_id) override; + void DeleteSession(const SessionKey& key) override; SessionsMap GetAllSessions() const override; void RestoreSessionBindingKey( const SchemefulSite& site,
diff --git a/net/device_bound_sessions/session_store_impl_unittest.cc b/net/device_bound_sessions/session_store_impl_unittest.cc index de125331..05b4ce2 100644 --- a/net/device_bound_sessions/session_store_impl_unittest.cc +++ b/net/device_bound_sessions/session_store_impl_unittest.cc
@@ -114,7 +114,8 @@ CreateSessionHelper(key_service, cfg.url, cfg.session_id, cfg.origin); EXPECT_TRUE(session); store.SaveSession(site, *session); - session_map.emplace(std::move(site), std::move(session)); + session_map.emplace(SessionKey{std::move(site), session->id()}, + std::move(session)); } return session_map; @@ -232,7 +233,7 @@ EXPECT_EQ(store().GetAllSessions().size(), 0u); // Verify that delete session call is ignored. - store().DeleteSession(site, session->id()); + store().DeleteSession(SessionKey{site, session->id()}); EXPECT_EQ(store().GetAllSessions().size(), 0u); // Verify that restore session binding key call fails. @@ -267,8 +268,8 @@ SessionStore::SessionsMap store_sessions = store().GetAllSessions(); // Restore the binding keys in the store session objects. - for (auto& [site, session] : store_sessions) { - RestoreSessionBindingKey(site, session.get()); + for (auto& [key, session] : store_sessions) { + RestoreSessionBindingKey(key.site, session.get()); } // Verify the session store contents. @@ -296,10 +297,11 @@ // match the updated data. SessionStore::SessionsMap store_sessions = store().GetAllSessions(); EXPECT_EQ(store_sessions.size(), 1u); - for (auto& [store_site, store_session] : store_sessions) { - EXPECT_TRUE(store_site == site); + for (auto& [key, store_session] : store_sessions) { + EXPECT_TRUE(key.site == site); + EXPECT_TRUE(key.id == store_session->id()); EXPECT_TRUE(store_session->expiry_date() == session->expiry_date()); - RestoreSessionBindingKey(store_site, store_session.get()); + RestoreSessionBindingKey(key.site, store_session.get()); EXPECT_TRUE(store_session->IsEqualForTesting(*session)); } } @@ -309,7 +311,7 @@ // Try to delete a session associated with a nonexisting site (in the store). auto site = net::SchemefulSite(GURL("https://foo.test")); - store().DeleteSession(site, Session::Id("session")); + store().DeleteSession(SessionKey{site, Session::Id("session")}); EXPECT_EQ(store().GetAllSessions().size(), 0u); // Create a session but don't save it to the store. @@ -338,7 +340,7 @@ unexportable_key_service(), "https://foo.test", "session2"); // Try to delete the unsaved session. - store().DeleteSession(site, session2->id()); + store().DeleteSession(SessionKey{site, session2->id()}); EXPECT_EQ(store().GetAllSessions().size(), 1u); // Try to restore the unsaved session's binding key. @@ -371,18 +373,21 @@ EXPECT_EQ(store_sessions.size(), 3u); // Delete the valid sessions one by one and check store contents. - store().DeleteSession(site2, Session::Id(cfgs[2].session_id)); + store().DeleteSession(SessionKey{site2, Session::Id(cfgs[2].session_id)}); store_sessions = store().GetAllSessions(); - EXPECT_TRUE(store_sessions.find(site2) == store_sessions.end()); + EXPECT_TRUE( + store_sessions.find(SessionKey{site2, Session::Id(cfgs[2].session_id)}) == + store_sessions.end()); - store().DeleteSession(site1, Session::Id(cfgs[0].session_id)); + store().DeleteSession(SessionKey{site1, Session::Id(cfgs[0].session_id)}); store_sessions = store().GetAllSessions(); EXPECT_EQ(store_sessions.size(), 1u); - EXPECT_EQ(store_sessions.begin()->first, site1); + SessionKey expected_key{site1, Session::Id(cfgs[1].session_id)}; + EXPECT_EQ(store_sessions.begin()->first, expected_key); EXPECT_EQ(store_sessions.begin()->second->id(), Session::Id(cfgs[1].session_id)); - store().DeleteSession(site1, Session::Id(cfgs[1].session_id)); + store().DeleteSession(SessionKey{site1, Session::Id(cfgs[1].session_id)}); store_sessions = store().GetAllSessions(); EXPECT_EQ(store_sessions.size(), 0u); } @@ -402,8 +407,8 @@ SessionStore::SessionsMap loaded_sessions = LoadSessions(); // Restore the binding keys in the store session objects. - for (auto& [site, session] : loaded_sessions) { - RestoreSessionBindingKey(site, session.get()); + for (auto& [key, session] : loaded_sessions) { + RestoreSessionBindingKey(key.site, session.get()); } EXPECT_TRUE(SessionMapsAreEqual(saved_sessions, loaded_sessions)); @@ -441,7 +446,8 @@ // - entry with invalid site is not present and is included in the // keys_to_delete list. EXPECT_EQ(sessions_map.size(), 1u); - EXPECT_EQ(sessions_map.count(site2), 1u); + SessionKey key{site2, Session::Id("session_id")}; + EXPECT_EQ(sessions_map.count(key), 1u); EXPECT_EQ(keys_to_delete.size(), 1u); EXPECT_EQ(keys_to_delete[0], "about:blank"); }
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc index a6e7ab5d..8a9da52 100644 --- a/net/http/bidirectional_stream_unittest.cc +++ b/net/http/bidirectional_stream_unittest.cc
@@ -476,14 +476,16 @@ } TEST_F(BidirectionalStreamTest, SimplePostRequest) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataString, /*fin=*/true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true)); MockRead reads[] = { @@ -521,17 +523,17 @@ } TEST_F(BidirectionalStreamTest, LoadTimingTwoRequests) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), /*stream_id=*/1, LOW)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), /*stream_id=*/3, LOW)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(req2, 2), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), /*stream_id=*/1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), /*stream_id=*/3)); spdy::SpdySerializedFrame resp_body( spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true)); spdy::SpdySerializedFrame resp_body2( @@ -610,8 +612,8 @@ MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body_frame( spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { @@ -670,9 +672,10 @@ CreateMockWrite(req, 0), }; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -746,16 +749,17 @@ // Tests that the NetLog contains correct entries. TEST_F(BidirectionalStreamTest, TestNetLogContainEntries) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataString, /*fin=*/true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body_frame1( spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame response_body_frame2( @@ -882,8 +886,9 @@ } TEST_F(BidirectionalStreamTest, TestInterleaveReadDataAndSendData) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame1( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataString, /*fin=*/false)); spdy::SpdySerializedFrame data_frame2( @@ -895,8 +900,8 @@ CreateMockWrite(data_frame2, 6), CreateMockWrite(data_frame3, 9), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body_frame1( spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame response_body_frame2( @@ -983,8 +988,9 @@ } TEST_F(BidirectionalStreamTest, TestCoalesceSmallDataBuffers) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 1, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 1, LOWEST, + base::span<const std::string_view>())); std::string body_data = "some really long piece of data"; spdy::SpdySerializedFrame data_frame1( spdy_util_.ConstructSpdyDataFrame(1, body_data, /*fin=*/true)); @@ -992,8 +998,8 @@ CreateMockWrite(req, 0), CreateMockWrite(data_frame1, 1), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body_frame1( spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { @@ -1081,8 +1087,8 @@ spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, "", true)); @@ -1134,9 +1140,10 @@ spdy_util_.ConstructSpdyGet(kDefaultUrl, 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -1211,9 +1218,10 @@ CreateMockWrite(req, 0), }; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -1279,8 +1287,9 @@ } TEST_F(BidirectionalStreamTest, DeleteStreamAfterSendData) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataString, /*fin=*/false)); spdy::SpdySerializedFrame rst( @@ -1291,8 +1300,8 @@ CreateMockWrite(rst, 5), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause. @@ -1341,8 +1350,9 @@ } TEST_F(BidirectionalStreamTest, DeleteStreamDuringReadData) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -1350,8 +1360,8 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 4), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -1403,8 +1413,9 @@ // Receiving a header with uppercase ASCII will result in a protocol error, // which should be propagated via Delegate::OnFailed. TEST_F(BidirectionalStreamTest, PropagateProtocolError) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); @@ -1412,9 +1423,9 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 2), }; - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; + const std::string_view kExtraHeaders[] = {"X-UpperCase", "yes"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), @@ -1473,9 +1484,10 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 2), }; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), @@ -1522,9 +1534,10 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 3), }; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -1575,9 +1588,10 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 4), }; - const char* const kExtraResponseHeaders[] = {"header-name", "header-value"}; + const std::string_view kExtraResponseHeaders[] = {"header-name", + "header-value"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -1634,9 +1648,9 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 2), }; - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; + const std::string_view kExtraHeaders[] = {"X-UpperCase", "yes"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), @@ -1679,10 +1693,10 @@ std::string alt_svc_header_value = quic::AlpnForVersion(DefaultSupportedQuicVersions().front()); alt_svc_header_value.append("=\"www.example.org:443\""); - const char* const kExtraResponseHeaders[] = {"alt-svc", - alt_svc_header_value.c_str()}; + const std::string_view kExtraResponseHeaders[] = {"alt-svc", + alt_svc_header_value}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); spdy::SpdySerializedFrame body_frame( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -1732,14 +1746,16 @@ // Test that a BidirectionalStream created with a specific tag, tags the // underlying socket appropriately. TEST_F(BidirectionalStreamTest, Tagging) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataString, /*fin=*/true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true)); MockRead reads[] = {
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index bbbc2ee0..3893bbe 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -1963,8 +1963,8 @@ spdy_resp1_headers[spdy::kHttp2StatusHeader] = "100"; spdy::SpdySerializedFrame spdy_resp1( spdy_util_.ConstructSpdyReply(1, spdy_resp1_headers.Clone())); - spdy::SpdySerializedFrame spdy_resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame spdy_resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame spdy_data( spdy_util_.ConstructSpdyDataFrame(1, "hello world", true)); @@ -2234,7 +2234,7 @@ spdy::SpdySerializedFrame spdy_request_body( spdy_util.ConstructSpdyDataFrame(1, "foobar", true)); spdy::SpdySerializedFrame spdy_response( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame spdy_data( spdy_util.ConstructSpdyDataFrame(1, "hello", true)); @@ -2415,7 +2415,8 @@ // Construct a non error HTTP2 response. spdy::SpdySerializedFrame spdy_response_no_error( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame spdy_data( spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead data_read2[] = {CreateMockRead(spdy_response_no_error, 1), @@ -6935,8 +6936,8 @@ spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -7020,26 +7021,28 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:80 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil spdy_util2(/*use_priority_header=*/true); spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 80))); spdy::SpdySerializedFrame wrapped_endpoint_connect( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -7175,26 +7178,27 @@ // CONNECT to proxy.test:70 via SPDY. spdy::SpdySerializedFrame proxy_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_1_.host_port_pair())); - spdy::SpdySerializedFrame proxy_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame proxy_connect_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // CONNECT to www.example.org:80 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil new_spdy_util(/*use_priority_header=*/true); spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 80))); spdy::SpdySerializedFrame wrapped_endpoint_connect( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -7319,19 +7323,20 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:80 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil spdy_util2(/*use_priority_header=*/true); spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 80))); spdy::SpdySerializedFrame wrapped_endpoint_connect( @@ -7410,7 +7415,7 @@ // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); @@ -7479,7 +7484,7 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); @@ -7603,19 +7608,20 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:80 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil spdy_util2(/*use_priority_header=*/true); spdy::SpdySerializedFrame endpoint_connect(spdy_util2.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 80))); spdy::SpdySerializedFrame wrapped_endpoint_connect( @@ -7697,12 +7703,13 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - /*extra_headers=*/nullptr, 0, 1, + base::span<const std::string_view>(), 1, HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -7777,18 +7784,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // CONNECT is calculated correctly. SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Since this request and response are sent over the tunnel established @@ -7798,7 +7808,8 @@ spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -7897,8 +7908,8 @@ spdy_util_.ConstructSpdyGet("http://www.example.org/", 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -7968,14 +7979,13 @@ // The first request will be a bare GET, the second request will be a // GET with a Proxy-Authorization header. spdy_util_.set_default_url(request.url); - spdy::SpdySerializedFrame req_get( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req_get(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy_util_.UpdateWithStreamDestruction(1); - const char* const kExtraAuthorizationHeaders[] = {"proxy-authorization", - "Basic Zm9vOmJhcg=="}; - spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet( - kExtraAuthorizationHeaders, std::size(kExtraAuthorizationHeaders) / 2, 3, - LOWEST)); + const std::string_view kExtraAuthorizationHeaders[] = {"proxy-authorization", + "Basic Zm9vOmJhcg=="}; + spdy::SpdySerializedFrame req_get_authorization( + spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 3, LOWEST)); MockWrite spdy_writes[] = { CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3), @@ -7984,16 +7994,15 @@ // The first response is a 407 proxy authentication challenge, and the second // response will be a 200 response since the second request includes a valid // Authorization header. - const char* const kExtraAuthenticationHeaders[] = { + const std::string_view kExtraAuthenticationHeaders[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\""}; spdy::SpdySerializedFrame resp_authentication( - spdy_util_.ConstructSpdyReplyError( - "407", kExtraAuthenticationHeaders, - std::size(kExtraAuthenticationHeaders) / 2, 1)); + spdy_util_.ConstructSpdyReplyError("407", kExtraAuthenticationHeaders, + 1)); spdy::SpdySerializedFrame body_authentication( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp_data( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body_data( spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead spdy_reads[] = { @@ -8067,7 +8076,8 @@ // CONNECT to www.example.org:443 via SPDY spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // fetch https://www.example.org/ via HTTP @@ -8077,8 +8087,8 @@ "Connection: keep-alive\r\n\r\n"; spdy::SpdySerializedFrame wrapped_get( spdy_util_.ConstructSpdyDataFrame(1, kGet, false)); - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); const char kResp[] = "HTTP/1.1 200 OK\r\n" "Content-Length: 10\r\n\r\n"; @@ -8157,18 +8167,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // CONNECT is calculated correctly. SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Since this request and response are sent over the tunnel established @@ -8178,7 +8191,8 @@ spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -8286,7 +8300,8 @@ // CONNECT to www.example.org:443 via SPDY spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // fetch https://www.example.org/ via SPDY const char kMyUrl[] = "https://www.example.org/"; @@ -8294,10 +8309,10 @@ spdy_util_wrapped.ConstructSpdyGet(kMyUrl, 1, LOWEST)); spdy::SpdySerializedFrame wrapped_get( spdy_util_.ConstructWrappedSpdyFrame(get, 1)); - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame get_resp( - spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame get_resp(spdy_util_wrapped.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp( spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); spdy::SpdySerializedFrame body( @@ -8395,11 +8410,13 @@ // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame endpoint_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame endpoint_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // fetch https://www.example.org/ via HTTP. // Since this request and response are sent over the tunnel established @@ -8494,11 +8511,13 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via HTTPS. const char kEndpointConnect[] = @@ -8606,7 +8625,8 @@ // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -8670,7 +8690,8 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_error_resp( spdy_util_.ConstructSpdyReplyError(1)); @@ -8735,18 +8756,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil new_spdy_util; // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame rst( new_spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -9048,18 +9072,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // CONNECT is calculated correctly. SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Since this request and response are sent over the tunnel established @@ -9069,7 +9096,8 @@ spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -9101,10 +9129,12 @@ const char kTrans2RespData[] = "abcdefghij"; spdy::SpdySerializedFrame second_trans_endpoint_connect( spdy_util_.ConstructSpdyConnect( - nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 3, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame second_trans_endpoint_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 3)); spdy::SpdySerializedFrame second_trans_wrapped_get( new_spdy_util.ConstructSpdyDataFrame(3, kGet, false)); spdy::SpdySerializedFrame second_trans_wrapped_get_resp( @@ -9212,11 +9242,13 @@ SpdyTestUtil third_spdy_util; spdy::SpdySerializedFrame third_trans_endpoint_connect( third_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame third_trans_endpoint_connect_resp( - third_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + third_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // fetch https://www.example.org/ via HTTP. spdy::SpdySerializedFrame third_trans_wrapped_get( @@ -9304,18 +9336,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // CONNECT is calculated correctly. SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Since the first request and response are sent over the tunnel established @@ -9325,7 +9360,8 @@ spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -9358,13 +9394,15 @@ // CONNECT to www.example.com:443 via SPDY. spdy::SpdySerializedFrame second_trans_endpoint_connect( new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 3, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.com", 443))); spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect( spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect, 1)); spdy::SpdySerializedFrame second_trans_endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 3)); spdy::SpdySerializedFrame second_trans_wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(second_trans_endpoint_connect_resp, 1)); @@ -9507,18 +9545,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, proxy_server_2_.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // CONNECT to www.example.org:443 via SPDY. // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // CONNECT is calculated correctly. SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Since this request and response are sent over the tunnel established @@ -9528,7 +9569,8 @@ spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect, 1)); spdy::SpdySerializedFrame endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(endpoint_connect_resp, 1)); @@ -9540,13 +9582,15 @@ new_spdy_util.UpdateWithStreamDestruction(1); spdy::SpdySerializedFrame attempt2_endpoint_connect( new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 3, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect( spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect, 1)); spdy::SpdySerializedFrame attempt2_endpoint_connect_resp( - new_spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + new_spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 3)); spdy::SpdySerializedFrame attempt2_wrapped_endpoint_connect_resp( spdy_util_.ConstructWrappedSpdyFrame(attempt2_endpoint_connect_resp, 1)); @@ -9692,15 +9736,15 @@ const char kMyUrl[] = "https://www.example.org/"; spdy::SpdySerializedFrame get(spdy_util_.ConstructSpdyGet(kMyUrl, 1, LOWEST)); - spdy::SpdySerializedFrame get_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame get_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy_util_.UpdateWithStreamDestruction(1); spdy::SpdySerializedFrame get2( spdy_util_.ConstructSpdyGet(kMyUrl, 3, LOWEST)); - spdy::SpdySerializedFrame get_resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame get_resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockWrite auth_challenge_writes[] = { @@ -9869,10 +9913,11 @@ // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); - spdy::SpdySerializedFrame conn_resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Fetch https://www.example.org/ via HTTP. const char kGet1[] = @@ -9898,8 +9943,8 @@ 3, std::move(connect2_block), HttpProxyConnectJob::kH2QuicTunnelPriority, false)); - spdy::SpdySerializedFrame conn_resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame conn_resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); // Fetch https://mail.example.org/ via HTTP. const char kGet2[] = @@ -10010,10 +10055,11 @@ // CONNECT to www.example.org:443 via SPDY. spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); - spdy::SpdySerializedFrame conn_resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Fetch https://www.example.org/ via HTTP. const char kGet1[] = @@ -10141,8 +10187,8 @@ spdy_util_.ConstructGetHeaderBlockForProxy("http://www.example.org/")); spdy::SpdySerializedFrame get1( spdy_util_.ConstructSpdyHeaders(1, std::move(headers), LOWEST, true)); - spdy::SpdySerializedFrame get_resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame get_resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(1, "1", true)); spdy_util_.UpdateWithStreamDestruction(1); @@ -10152,8 +10198,8 @@ spdy_util_.ConstructGetHeaderBlockForProxy("http://mail.example.org/")); spdy::SpdySerializedFrame get2( spdy_util_.ConstructSpdyHeaders(3, std::move(headers2), LOWEST, true)); - spdy::SpdySerializedFrame get_resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame get_resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2( spdy_util_.ConstructSpdyDataFrame(3, "22", true)); @@ -10238,17 +10284,18 @@ SpdyTestUtil spdy_util1(/*use_priority_header=*/true); // CONNECT to www.example.org:443 via HTTP/2. spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // fetch https://www.example.org/ via HTTP/2. const char kMyUrl[] = "https://www.example.org/"; spdy::SpdySerializedFrame get(spdy_util1.ConstructSpdyGet(kMyUrl, 1, LOWEST)); spdy::SpdySerializedFrame wrapped_get( spdy_util_.ConstructWrappedSpdyFrame(get, 1)); - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame get_resp( - spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame get_resp(spdy_util1.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp( spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); spdy::SpdySerializedFrame body(spdy_util1.ConstructSpdyDataFrame(1, true)); @@ -10284,8 +10331,8 @@ spdy_util2.ConstructSpdyGet("https://proxy:70/", 1, LOWEST)); MockWrite spdy_writes2[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads2[] = { CreateMockRead(resp, 1), @@ -10375,8 +10422,8 @@ spdy_util1.ConstructSpdyGet("https://proxy:70/", 1, LOWEST)); MockWrite spdy_writes1[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util1.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util1.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads1[] = { CreateMockRead(resp, 1), @@ -10389,17 +10436,18 @@ SpdyTestUtil spdy_util2(/*use_priority_header=*/true); // CONNECT to www.example.org:443 via HTTP/2. spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // fetch https://www.example.org/ via HTTP/2. const char kMyUrl[] = "https://www.example.org/"; spdy::SpdySerializedFrame get(spdy_util2.ConstructSpdyGet(kMyUrl, 1, LOWEST)); spdy::SpdySerializedFrame wrapped_get( spdy_util_.ConstructWrappedSpdyFrame(get, 1)); - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame get_resp( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame get_resp(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp( spdy_util_.ConstructWrappedSpdyFrame(get_resp, 1)); spdy::SpdySerializedFrame body(spdy_util2.ConstructSpdyDataFrame(1, true)); @@ -12255,8 +12303,8 @@ // Response headers for first request. Body is never received, but that // shouldn't matter for the purposes of this test. - spdy::SpdySerializedFrame initial_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame initial_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // First WebSocket request, which has no credentials. quiche::HttpHeaderBlock websocket_request_headers; @@ -14549,7 +14597,8 @@ MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame goaway( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -14558,12 +14607,12 @@ CreateMockWrite(goaway, 3, SYNCHRONOUS), }; - static const char* const kExtraHeaders[] = { + static const std::string_view kExtraHeaders[] = { "location", "http://login.example.com/", }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError( - "302", kExtraHeaders, std::size(kExtraHeaders) / 2, 1)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyReplyError("302", kExtraHeaders, 1)); MockRead data_reads[] = { // Pause on first read. MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2), @@ -14661,7 +14710,8 @@ MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); spdy::SpdySerializedFrame conn(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -14670,12 +14720,12 @@ CreateMockWrite(rst, 3), }; - static const char* const kExtraHeaders[] = { + static const std::string_view kExtraHeaders[] = { "location", "http://login.example.com/", }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError( - "404", kExtraHeaders, std::size(kExtraHeaders) / 2, 1)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyReplyError("404", kExtraHeaders, 1)); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, "The host does not exist", true)); MockRead data_reads[] = { @@ -14725,7 +14775,8 @@ // Since we have proxy, should try to establish tunnel. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -14733,15 +14784,14 @@ // After calling trans.RestartWithAuth(), this is the request we should // be issuing -- the final header line contains the credentials. - const char* const kAuthCredentials[] = { + const std::string_view kAuthCredentials[] = { "user-agent", "test-ua", "proxy-authorization", "Basic Zm9vOmJhcg==", }; spdy::SpdySerializedFrame connect2(spdy_util_.ConstructSpdyConnect( - kAuthCredentials, std::size(kAuthCredentials) / 2, 3, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kAuthCredentials, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // fetch https://www.example.org/ via HTTP const char kGet[] = @@ -14761,15 +14811,15 @@ // The proxy responds to the connect with a 407, using a persistent // connection. const char kAuthStatus[] = "407"; - const char* const kAuthChallenge[] = { + const std::string_view kAuthChallenge[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\"", }; - spdy::SpdySerializedFrame conn_auth_resp(spdy_util_.ConstructSpdyReplyError( - kAuthStatus, kAuthChallenge, std::size(kAuthChallenge) / 2, 1)); + spdy::SpdySerializedFrame conn_auth_resp( + spdy_util_.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1)); - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); const char kResp[] = "HTTP/1.1 200 OK\r\n" "Content-Length: 5\r\n\r\n"; @@ -17577,8 +17627,8 @@ spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -17681,11 +17731,11 @@ CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame data2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead spdy_reads[] = { CreateMockRead(resp1, 2), CreateMockRead(data1, 3), @@ -17882,8 +17932,8 @@ MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -17968,8 +18018,8 @@ const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n"; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { MockRead(ASYNC, 1, kCONNECTResponse), @@ -18066,8 +18116,8 @@ spdy_util_.ConstructSpdyGet("https://www.example.org/", 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -19370,8 +19420,8 @@ ssl.next_proto = NextProto::kProtoHTTP2; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 1)}; MockRead spdy_reads[] = { @@ -19800,8 +19850,8 @@ spdy_util_.ConstructSpdyGet("https://www.example.org", 1, LOWEST)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy_reads[] = { CreateMockRead(resp, 1), @@ -20354,12 +20404,12 @@ CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), }; - spdy::SpdySerializedFrame host1_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame host1_resp_body( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame host2_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame host2_resp_body( spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead spdy_reads[] = { @@ -20450,12 +20500,12 @@ CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), }; - spdy::SpdySerializedFrame host1_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame host1_resp_body( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame host2_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame host2_resp_body( spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead spdy_reads[] = { @@ -20537,10 +20587,11 @@ // CONNECT to request1.test:443 via SPDY. spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("request1.test", 443))); - spdy::SpdySerializedFrame conn_resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Fetch https://www.example.org/ via SPDY. SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true); @@ -20548,8 +20599,8 @@ req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST)); spdy::SpdySerializedFrame wrapped_get1( spdy_util_.ConstructWrappedSpdyFrame(get1, 1)); - spdy::SpdySerializedFrame get_resp1( - req1_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame get_resp1(req1_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp1( spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1)); @@ -20619,8 +20670,8 @@ spdy::SpdySerializedFrame req2( req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST)); - spdy::SpdySerializedFrame resp2( - req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data2( req2_spdy_util.ConstructSpdyDataFrame(1, true)); @@ -20685,8 +20736,8 @@ spdy::SpdySerializedFrame req( spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; @@ -20736,8 +20787,8 @@ spdy::SpdySerializedFrame req2( req2_spdy_util.ConstructSpdyGet("https://mail.example.com/", 1, LOWEST)); - spdy::SpdySerializedFrame resp2( - req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data2( req2_spdy_util.ConstructSpdyDataFrame(1, true)); @@ -20808,10 +20859,11 @@ // CONNECT to request1.test:443 via SPDY. spdy::SpdySerializedFrame connect1(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("request1.test", 443))); - spdy::SpdySerializedFrame conn_resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Fetch https://www.example.org/ via SPDY. SpdyTestUtil req1_spdy_util(/*use_priority_header=*/true); @@ -20819,8 +20871,8 @@ req1_spdy_util.ConstructSpdyGet("https://request1.test/", 1, LOWEST)); spdy::SpdySerializedFrame wrapped_get1( spdy_util_.ConstructWrappedSpdyFrame(get1, 1)); - spdy::SpdySerializedFrame get_resp1( - req1_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame get_resp1(req1_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp1( spdy_util_.ConstructWrappedSpdyFrame(get_resp1, 1)); @@ -20889,10 +20941,11 @@ // CONNECT to request2.test:443 via SPDY. SpdyTestUtil req2_spdy_util(/*use_priority_header=*/true); spdy::SpdySerializedFrame connect2(req2_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("request2.test", 443))); - spdy::SpdySerializedFrame conn_resp2( - req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp2(req2_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Fetch https://www.example.org/ via SPDY. SpdyTestUtil wrapped_req2_spdy_util(/*use_priority_header=*/true); @@ -20901,7 +20954,8 @@ spdy::SpdySerializedFrame wrapped_get2( req2_spdy_util.ConstructWrappedSpdyFrame(get2, 1)); spdy::SpdySerializedFrame get_resp2( - wrapped_req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + wrapped_req2_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_get_resp2( req2_spdy_util.ConstructWrappedSpdyFrame(get_resp2, 1)); @@ -20990,8 +21044,8 @@ spdy::SpdySerializedFrame req( spdy_util_.ConstructSpdyGet("http://request1.test/", 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; @@ -21041,8 +21095,8 @@ spdy::SpdySerializedFrame req2( req2_spdy_util.ConstructSpdyGet("http://request2.test/", 1, LOWEST)); - spdy::SpdySerializedFrame resp2( - req2_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(req2_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data2( req2_spdy_util.ConstructSpdyDataFrame(1, true)); @@ -21115,8 +21169,8 @@ // The first request succeeds, the second request gets error 421 Misdirected // Request. The first H2 connection remains available after getting 421. - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); quiche::HttpHeaderBlock response_headers; response_headers[spdy::kHttp2StatusHeader] = "421"; @@ -21141,8 +21195,8 @@ CreateMockWrite(req3, 0), }; - spdy::SpdySerializedFrame resp3( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp3(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2), MockRead(ASYNC, 0, 3)}; @@ -21245,8 +21299,8 @@ }; // The first one succeeds, the second gets error 421 Misdirected Request. - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); quiche::HttpHeaderBlock response_headers; response_headers[spdy::kHttp2StatusHeader] = "421"; @@ -21351,7 +21405,8 @@ std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); const std::string request_body = "hello"; - spdy::SpdySerializedFrame req1 = spdy_util_.ConstructChunkedSpdyPost({}, 0); + spdy::SpdySerializedFrame req1 = + spdy_util_.ConstructChunkedSpdyPost(base::span<const std::string_view>()); spdy::SpdySerializedFrame req1_body = spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true); spdy::SpdySerializedFrame rst = @@ -21375,7 +21430,8 @@ AddSSLSocketData(); SpdyTestUtil spdy_util2(/*use_priority_header=*/true); - spdy::SpdySerializedFrame req2 = spdy_util2.ConstructChunkedSpdyPost({}, 0); + spdy::SpdySerializedFrame req2 = + spdy_util2.ConstructChunkedSpdyPost(base::span<const std::string_view>()); spdy::SpdySerializedFrame req2_body = spdy_util2.ConstructSpdyDataFrame(1, request_body, /*fin=*/true); MockWrite writes2[] = { @@ -21440,7 +21496,8 @@ std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); const std::string request_body = "hello"; - spdy::SpdySerializedFrame req1 = spdy_util_.ConstructChunkedSpdyPost({}, 0); + spdy::SpdySerializedFrame req1 = + spdy_util_.ConstructChunkedSpdyPost(base::span<const std::string_view>()); spdy::SpdySerializedFrame req1_body = spdy_util_.ConstructSpdyDataFrame(1, request_body, /*fin=*/true); spdy::SpdySerializedFrame rst = @@ -21517,12 +21574,12 @@ CreateMockWrite(host1_req, 0), CreateMockWrite(host2_req, 3), }; - spdy::SpdySerializedFrame host1_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame host1_resp_body( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame host2_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame host2_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame host2_resp_body( spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead spdy_reads[] = { @@ -21598,8 +21655,8 @@ CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -21944,8 +22001,8 @@ // SPDY GET for HTTPS URL (through CONNECT tunnel) const HostPortPair host_port_pair("www.example.org", 8080); spdy::SpdySerializedFrame connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, - host_port_pair)); + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, host_port_pair)); spdy::SpdySerializedFrame req1( spdy_util_wrapped.ConstructSpdyGet(https_url.c_str(), 1, LOWEST)); spdy::SpdySerializedFrame wrapped_req1( @@ -21966,18 +22023,18 @@ CreateMockWrite(req2, 6), }; - spdy::SpdySerializedFrame conn_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp1( - spdy_util_wrapped.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame conn_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp1(spdy_util_wrapped.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1( spdy_util_wrapped.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame wrapped_resp1( spdy_util_wrapped.ConstructWrappedSpdyFrame(resp1, 1)); spdy::SpdySerializedFrame wrapped_body1( spdy_util_wrapped.ConstructWrappedSpdyFrame(body1, 1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads1[] = { CreateMockRead(conn_resp, 1), @@ -22081,8 +22138,8 @@ CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = { MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp1, 2), @@ -22104,8 +22161,8 @@ CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util_secure.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util_secure.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2( spdy_util_secure.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2), @@ -22201,8 +22258,8 @@ CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = { CreateMockRead(resp2, 1), CreateMockRead(body2, 2), @@ -22283,8 +22340,8 @@ MockWrite spdy1_writes[] = { CreateMockWrite(host1_req, 0), }; - spdy::SpdySerializedFrame host1_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame host1_resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame host1_resp_body( spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead spdy1_reads[] = { @@ -22304,8 +22361,8 @@ MockWrite spdy2_writes[] = { CreateMockWrite(host2_req, 0), }; - spdy::SpdySerializedFrame host2_resp( - spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame host2_resp(spdy_util_2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame host2_resp_body( spdy_util_2.ConstructSpdyDataFrame(1, true)); MockRead spdy2_reads[] = { @@ -24830,8 +24887,8 @@ }; // The first one succeeds, the second gets error 421 Misdirected Request. - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); quiche::HttpHeaderBlock response_headers; response_headers[spdy::kHttp2StatusHeader] = "421"; @@ -24854,8 +24911,8 @@ CreateMockWrite(req3, 0), }; - spdy::SpdySerializedFrame resp3( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp3(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body3(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp3, 1), CreateMockRead(body3, 2), MockRead(ASYNC, 0, 3)}; @@ -26644,7 +26701,8 @@ spdy::SpdySerializedFrame unpartitioned_req1( spdy_util.ConstructSpdyGet(url1, 1, LOWEST)); spdy::SpdySerializedFrame unpartitioned_response1( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame unpartitioned_body1( spdy_util.ConstructSpdyDataFrame(1, "1", true)); spdy_util.UpdateWithStreamDestruction(1); @@ -26652,7 +26710,8 @@ spdy::SpdySerializedFrame unpartitioned_req2( spdy_util.ConstructSpdyGet(url2, 3, LOWEST)); spdy::SpdySerializedFrame unpartitioned_response2( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 3)); spdy::SpdySerializedFrame unpartitioned_body2( spdy_util.ConstructSpdyDataFrame(3, "2", true)); spdy_util.UpdateWithStreamDestruction(3); @@ -26660,7 +26719,8 @@ spdy::SpdySerializedFrame unpartitioned_req3( spdy_util.ConstructSpdyGet(url3, 5, LOWEST)); spdy::SpdySerializedFrame unpartitioned_response3( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), + 5)); spdy::SpdySerializedFrame unpartitioned_body3( spdy_util.ConstructSpdyDataFrame(5, "3", true)); @@ -26689,7 +26749,8 @@ spdy::SpdySerializedFrame partitioned_req1( spdy_util2.ConstructSpdyGet(url1, 1, LOWEST)); spdy::SpdySerializedFrame partitioned_response1( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame partitioned_body1( spdy_util2.ConstructSpdyDataFrame(1, "1", true)); spdy_util2.UpdateWithStreamDestruction(1); @@ -26697,7 +26758,8 @@ spdy::SpdySerializedFrame partitioned_req3( spdy_util2.ConstructSpdyGet(url3, 3, LOWEST)); spdy::SpdySerializedFrame partitioned_response3( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy_util2.ConstructSpdyGetReply(base::span<const std::string_view>(), + 3)); spdy::SpdySerializedFrame partitioned_body3( spdy_util2.ConstructSpdyDataFrame(3, "3", true)); @@ -26718,7 +26780,8 @@ spdy::SpdySerializedFrame partitioned_req2( spdy_util3.ConstructSpdyGet(url2, 1, LOWEST)); spdy::SpdySerializedFrame partitioned_response2( - spdy_util3.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util3.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); spdy::SpdySerializedFrame partitioned_body2( spdy_util3.ConstructSpdyDataFrame(1, "2", true));
diff --git a/net/http/http_proxy_connect_job_unittest.cc b/net/http/http_proxy_connect_job_unittest.cc index 77021f4..99e67ce 100644 --- a/net/http/http_proxy_connect_job_unittest.cc +++ b/net/http/http_proxy_connect_job_unittest.cc
@@ -579,11 +579,12 @@ // SPDY proxy CONNECT request / response, with a pause during the read. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = { // Pause at first read. MockRead(ASYNC, ERR_IO_PENDING, 1), @@ -689,23 +690,22 @@ MockRead(ASYNC, 1, http1_response.c_str()), }; - const char* const kExtraRequestHeaders[] = { + const std::string_view kExtraRequestHeaders[] = { kTestSpdyHeaderName, proxy_server_uri.c_str(), "user-agent", "test-ua", }; - const char* const kExtraResponseHeaders[] = { + const std::string_view kExtraResponseHeaders[] = { kResponseHeaderName, kResponseHeaderValue, }; spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - kExtraRequestHeaders, std::size(kExtraRequestHeaders) / 2, 1, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kExtraRequestHeaders, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( - kExtraResponseHeaders, std::size(kExtraResponseHeaders) / 2, 1)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyGetReply(kExtraResponseHeaders, 1)); MockRead spdy_reads[] = { CreateMockRead(resp, 1, ASYNC), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 2), @@ -778,35 +778,34 @@ MockRead(ASYNC, 3, second_hop_http1_response.c_str()), }; - const char* const kFirstHopExtraRequestHeaders[] = { + const std::string_view kFirstHopExtraRequestHeaders[] = { kTestSpdyHeaderName, - first_hop_proxy_server_uri.c_str(), + first_hop_proxy_server_uri, "user-agent", "test-ua", }; - const char* const kSecondHopExtraRequestHeaders[] = { + const std::string_view kSecondHopExtraRequestHeaders[] = { kTestSpdyHeaderName, - second_hop_proxy_server_uri.c_str(), + second_hop_proxy_server_uri, "user-agent", "test-ua", }; - const char* const kFirstHopExtraResponseHeaders[] = { + const std::string_view kFirstHopExtraResponseHeaders[] = { kResponseHeaderName, - first_hop_proxy_server_uri.c_str(), + first_hop_proxy_server_uri, }; - const char* const kSecondHopExtraResponseHeaders[] = { + const std::string_view kSecondHopExtraResponseHeaders[] = { kResponseHeaderName, - second_hop_proxy_server_uri.c_str(), + second_hop_proxy_server_uri, }; spdy::SpdySerializedFrame first_hop_req(spdy_util_.ConstructSpdyConnect( - kFirstHopExtraRequestHeaders, std::size(kFirstHopExtraRequestHeaders) / 2, - 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + kFirstHopExtraRequestHeaders, 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, second_hop_proxy_server.host_port_pair())); - spdy::SpdySerializedFrame first_hop_resp(spdy_util_.ConstructSpdyGetReply( - kFirstHopExtraResponseHeaders, - std::size(kFirstHopExtraResponseHeaders) / 2, 1)); + spdy::SpdySerializedFrame first_hop_resp( + spdy_util_.ConstructSpdyGetReply(kFirstHopExtraResponseHeaders, 1)); // Use a new `SpdyTestUtil()` instance for the second hop response and request // because otherwise, the serialized frames that get generated for these will @@ -816,8 +815,7 @@ SpdyTestUtil new_spdy_util; spdy::SpdySerializedFrame second_hop_req(new_spdy_util.ConstructSpdyConnect( - kSecondHopExtraRequestHeaders, - std::size(kSecondHopExtraRequestHeaders) / 2, 1, + kSecondHopExtraRequestHeaders, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); @@ -827,9 +825,8 @@ spdy::SpdySerializedFrame wrapped_second_hop_req( spdy_util_.ConstructWrappedSpdyFrame(second_hop_req, 1)); - spdy::SpdySerializedFrame second_hop_resp(new_spdy_util.ConstructSpdyGetReply( - kSecondHopExtraResponseHeaders, - std::size(kSecondHopExtraResponseHeaders) / 2, 1)); + spdy::SpdySerializedFrame second_hop_resp( + new_spdy_util.ConstructSpdyGetReply(kSecondHopExtraResponseHeaders, 1)); spdy::SpdySerializedFrame wrapped_second_hop_resp( spdy_util_.ConstructWrappedSpdyFrame(second_hop_resp, 1)); @@ -909,7 +906,8 @@ SpdyTestUtil spdy_util; spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); spdy::SpdySerializedFrame rst( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -917,15 +915,14 @@ // After calling trans.RestartWithAuth(), this is the request we should // be issuing -- the final header line contains the credentials. - const char* const kSpdyAuthCredentials[] = { + const std::string_view kSpdyAuthCredentials[] = { "user-agent", "test-ua", "proxy-authorization", "Basic Zm9vOmJhcg==", }; spdy::SpdySerializedFrame connect2(spdy_util.ConstructSpdyConnect( - kSpdyAuthCredentials, std::size(kSpdyAuthCredentials) / 2, 3, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kSpdyAuthCredentials, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = { @@ -937,16 +934,15 @@ // The proxy responds to the connect with a 407, using a persistent // connection. const char kAuthStatus[] = "407"; - const char* const kAuthChallenge[] = { + const std::string_view kAuthChallenge[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\"", }; spdy::SpdySerializedFrame connect_auth_resp( - spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, - std::size(kAuthChallenge) / 2, 1)); + spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1)); - spdy::SpdySerializedFrame connect2_resp( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame connect2_resp(spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead spdy_reads[] = { CreateMockRead(connect_auth_resp, 1, ASYNC), CreateMockRead(connect2_resp, 4, ASYNC), @@ -1032,7 +1028,8 @@ SpdyTestUtil spdy_util; spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); spdy::SpdySerializedFrame rst( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -1040,23 +1037,21 @@ // After calling trans.RestartWithAuth(), this is the request we should // be issuing -- the final header line contains the credentials. - const char* const kSpdyAuthCredentials[] = { + const std::string_view kSpdyAuthCredentials[] = { "user-agent", "test-ua", "proxy-authorization", "Basic Zm9vOmJhcg==", }; spdy::SpdySerializedFrame connect2(spdy_util.ConstructSpdyConnect( - kSpdyAuthCredentials, std::size(kSpdyAuthCredentials) / 2, 3, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kSpdyAuthCredentials, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); spdy::SpdySerializedFrame rst2( spdy_util.ConstructSpdyRstStream(3, spdy::ERROR_CODE_CANCEL)); spdy_util.UpdateWithStreamDestruction(3); spdy::SpdySerializedFrame connect3(spdy_util.ConstructSpdyConnect( - kSpdyAuthCredentials, std::size(kSpdyAuthCredentials) / 2, 5, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kSpdyAuthCredentials, 5, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = { CreateMockWrite(connect, 0, io_mode), @@ -1069,18 +1064,16 @@ // The proxy responds to the connect with a 407, using a persistent // connection. const char kAuthStatus[] = "407"; - const char* const kAuthChallenge[] = { + const std::string_view kAuthChallenge[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\"", }; spdy::SpdySerializedFrame connect_auth_resp( - spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, - std::size(kAuthChallenge) / 2, 1)); + spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1)); spdy::SpdySerializedFrame connect2_auth_resp( - spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, - std::size(kAuthChallenge) / 2, 3)); - spdy::SpdySerializedFrame connect3_resp( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 3)); + spdy::SpdySerializedFrame connect3_resp(spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); MockRead spdy_reads[] = { CreateMockRead(connect_auth_resp, 1, ASYNC), CreateMockRead(connect2_auth_resp, 4, ASYNC), @@ -1168,7 +1161,7 @@ MockRead(io_mode, 1, "HTTP/1.1 200 Connection Established\r\n\r\n"), }; - const char* const kSpdyAuthCredentials[] = { + const std::string_view kSpdyAuthCredentials[] = { "user-agent", "test-ua", "proxy-authorization", @@ -1176,16 +1169,15 @@ }; SpdyTestUtil spdy_util; spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - kSpdyAuthCredentials, std::size(kSpdyAuthCredentials) / 2, 1, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kSpdyAuthCredentials, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = { CreateMockWrite(connect, 0, ASYNC), }; - spdy::SpdySerializedFrame connect_resp( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_resp(spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = { // SpdySession starts trying to read from the socket as soon as it's // created, so this cannot be SYNCHRONOUS. @@ -1282,11 +1274,12 @@ // SPDY proxy CONNECT request / response, with a pause during the read. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)}; SequencedSocketData spdy_data(spdy_reads, spdy_writes); spdy_data.set_connect_data(MockConnect(ASYNC, OK)); @@ -1331,12 +1324,12 @@ // even though the ConnectJob's priority is set to HIGHEST after connection // establishment. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr /* extra_headers */, 0 /* extra_header_count */, - 1 /* stream_id */, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1 /* stream_id */, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0, ASYNC)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = {CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 2)}; @@ -1416,11 +1409,12 @@ // SPDY proxy CONNECT request / response, with a pause during the read. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)}; SequencedSocketData spdy_data(spdy_reads, spdy_writes); spdy_data.set_connect_data(MockConnect(ASYNC, OK)); @@ -1497,11 +1491,12 @@ // SPDY proxy CONNECT request / response, with a pause during the read. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead spdy_reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 2)}; SequencedSocketData spdy_data(spdy_reads, spdy_writes); spdy_data.set_connect_data(MockConnect(ASYNC, OK)); @@ -1611,8 +1606,8 @@ MockRead(io_mode, ERR_CONNECTION_CLOSED, 2), }; spdy::SpdySerializedFrame req(SpdyTestUtil().ConstructSpdyConnect( - nullptr /*extra_headers */, 0 /*extra_header_count */, - 1 /* stream_id */, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1 /* stream_id */, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); MockWrite spdy_writes[] = {CreateMockWrite(req, 0, io_mode)}; // Sync reads don't really work with SPDY, since it constantly reads from @@ -1694,8 +1689,8 @@ }; SpdyTestUtil spdy_util; spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyConnect( - nullptr /* extra_headers */, 0 /* extra_header_count */, - 1 /* stream_id */, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1 /* stream_id */, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.endpoint.test", 443))); spdy::SpdySerializedFrame rst( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -1785,8 +1780,8 @@ }; SpdyTestUtil spdy_util; spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyConnect( - nullptr /* extra_headers */, 0 /* extra_header_count */, 1, - DEFAULT_PRIORITY, HostPortPair(kEndpointHost, 443))); + base::span<const std::string_view>(), 1, DEFAULT_PRIORITY, + HostPortPair(kEndpointHost, 443))); spdy::SpdySerializedFrame rst( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); @@ -1795,15 +1790,14 @@ CreateMockWrite(rst, 3, io_mode), }; - const char* const responseHeaders[] = { + const std::string_view kResponseHeaders[] = { "location", - kRedirectTarget.c_str(), + kRedirectTarget, "set-cookie", "foo=bar", }; - const int responseHeadersSize = std::size(responseHeaders) / 2; - spdy::SpdySerializedFrame resp(spdy_util.ConstructSpdyReplyError( - "302", responseHeaders, responseHeadersSize, 1)); + spdy::SpdySerializedFrame resp( + spdy_util.ConstructSpdyReplyError("302", kResponseHeaders, 1)); MockRead spdy_reads[] = { CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, 0, 2), @@ -1879,24 +1873,24 @@ }; SpdyTestUtil spdy_util; - spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, - HostPortPair(kEndpointHost, 443))); + spdy::SpdySerializedFrame connect( + spdy_util.ConstructSpdyConnect(base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, + HostPortPair(kEndpointHost, 443))); spdy::SpdySerializedFrame rst( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); spdy_util.UpdateWithStreamDestruction(1); // After calling trans.RestartWithAuth(), this is the request we should // be issuing -- the final header line contains the credentials. - const char* const kSpdyAuthCredentials[] = { + const std::string_view kSpdyAuthCredentials[] = { "user-agent", "test-ua", "proxy-authorization", "Basic Zm9vOmJhcg==", }; spdy::SpdySerializedFrame connect2(spdy_util.ConstructSpdyConnect( - kSpdyAuthCredentials, std::size(kSpdyAuthCredentials) / 2, 3, - HttpProxyConnectJob::kH2QuicTunnelPriority, + kSpdyAuthCredentials, 3, HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair(kEndpointHost, 443))); // This may be sent in some tests, either when tearing down a successful // connection, or on timeout. @@ -1912,14 +1906,14 @@ // The proxy responds to the connect with a 407, using a persistent // connection. const char kAuthStatus[] = "407"; - const char* const kAuthChallenge[] = { + const std::string_view kAuthChallenge[] = { "proxy-authenticate", "Basic realm=\"MyRealm1\"", }; - spdy::SpdySerializedFrame connect_auth_resp(spdy_util.ConstructSpdyReplyError( - kAuthStatus, kAuthChallenge, std::size(kAuthChallenge) / 2, 1)); + spdy::SpdySerializedFrame connect_auth_resp( + spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1)); spdy::SpdySerializedFrame connect2_resp( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 3)); MockRead spdy_reads[] = { // Pause before first response is read. MockRead(ASYNC, ERR_IO_PENDING, 1),
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index ed049c17..95c7331 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2025-06-18 12:55 UTC +# Last updated: 2025-06-20 12:54 UTC PinsListTimestamp -1750251357 +1750424078 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index 7d7158f9..7a5ab26 100644 --- a/net/http/transport_security_state_static_pins.json +++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2025-06-18 12:55 UTC +// Last updated: 2025-06-20 12:54 UTC // { "pinsets": [
diff --git a/net/log/net_log_source_type_list.h b/net/log/net_log_source_type_list.h index f33da93..1a8bfe2 100644 --- a/net/log/net_log_source_type_list.h +++ b/net/log/net_log_source_type_list.h
@@ -37,6 +37,7 @@ SOURCE_TYPE(UDP_SOCKET) SOURCE_TYPE(CERT_VERIFY_PROC_CREATED) SOURCE_TYPE(CERT_VERIFIER_JOB) +SOURCE_TYPE(CERT_VERIFIER_2QWAC_JOB) SOURCE_TYPE(CERT_VERIFIER_TASK) SOURCE_TYPE(PROXY_CLIENT_SOCKET) SOURCE_TYPE(BIDIRECTIONAL_STREAM)
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index e5bdc21f..4f4b565 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -6807,7 +6807,7 @@ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), 1, 1, false, ConstructDataFrame({get_frame.data(), get_frame.size()}))); spdy::SpdySerializedFrame resp_frame = - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 1); mock_quic_data.AddRead( ASYNC, ConstructServerDataPacket( 2, GetNthClientInitiatedBidirectionalStreamId(0), false, @@ -7321,7 +7321,7 @@ false, ConstructDataFrame({get_frame.data(), get_frame.size()}))); spdy::SpdySerializedFrame resp_frame = - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 1); mock_quic_data.AddRead( ASYNC, ConstructServerDataPacket( 5, GetNthClientInitiatedBidirectionalStreamId(1), false,
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc index 037a1fb..c2849d8 100644 --- a/net/socket/transport_client_socket_pool_unittest.cc +++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -1592,7 +1592,8 @@ SpdyTestUtil spdy_util; spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair::FromSchemeHostPort(kEndpoint))); MockWrite writes[] = { @@ -1683,7 +1684,8 @@ SpdyTestUtil spdy_util; spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair::FromSchemeHostPort(kEndpoint))); MockWrite writes[] = { @@ -1695,12 +1697,12 @@ // ERROR_CODE_HTTP_1_1_REQUIRED. const char kAuthStatus[] = "407"; - const char* const kAuthChallenge[] = { + const std::string_view kAuthChallenge[] = { "proxy-authenticate", "NTLM", }; - spdy::SpdySerializedFrame connect_auth_resp(spdy_util.ConstructSpdyReplyError( - kAuthStatus, kAuthChallenge, std::size(kAuthChallenge) / 2, 1)); + spdy::SpdySerializedFrame connect_auth_resp( + spdy_util.ConstructSpdyReplyError(kAuthStatus, kAuthChallenge, 1)); spdy::SpdySerializedFrame reset( spdy_util.ConstructSpdyRstStream(1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED)); MockRead reads[] = {
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc index 92746178..9cd89bf 100644 --- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc +++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -302,14 +302,16 @@ }; TEST_F(BidirectionalStreamSpdyImplTest, SimplePostRequest) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame( 1, std::string_view(kBodyData, kBodyDataSize), /*fin=*/true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true)); MockRead reads[] = { @@ -351,17 +353,17 @@ } TEST_F(BidirectionalStreamSpdyImplTest, LoadTimingTwoRequests) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/1, LOW)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, /*stream_id=*/3, LOW)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), /*stream_id=*/1, LOW)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), /*stream_id=*/3, LOW)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(req2, 2), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, /*stream_id=*/3)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), /*stream_id=*/1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), /*stream_id=*/3)); spdy::SpdySerializedFrame resp_body( spdy_util_.ConstructSpdyDataFrame(/*stream_id=*/1, /*fin=*/true)); spdy::SpdySerializedFrame resp_body2( @@ -399,8 +401,9 @@ } TEST_F(BidirectionalStreamSpdyImplTest, SendDataAfterStreamFailed) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); @@ -408,9 +411,9 @@ CreateMockWrite(req, 0), CreateMockWrite(rst, 2), }; - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; + const std::string_view kExtraHeaders[] = {"X-UpperCase", "yes"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1, 1)); + spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3), @@ -458,11 +461,13 @@ // not crash when processing pending writes. See crbug.com/650438. TEST_P(BidirectionalStreamSpdyImplTest, RstWithNoErrorBeforeSendIsComplete) { bool is_test_sendv = GetParam(); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize * 3, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize * 3, LOW, + base::span<const std::string_view>())); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR)); MockRead reads[] = {CreateMockRead(resp, 1), @@ -540,15 +545,17 @@ } TEST_F(BidirectionalStreamSpdyImplTest, RequestDetectBrokenConnection) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOW, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOW, + base::span<const std::string_view>())); spdy::SpdySerializedFrame data_frame(spdy_util_.ConstructSpdyDataFrame( 1, std::string_view(kBodyData, kBodyDataSize), /*fin=*/true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(data_frame, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame response_body_frame( spdy_util_.ConstructSpdyDataFrame(1, /*fin=*/true)); MockRead reads[] = {
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc index 31bc3b1..e88aeeb9 100644 --- a/net/spdy/spdy_http_stream_unittest.cc +++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -185,13 +185,13 @@ }; TEST_F(SpdyHttpStreamTest, SendRequest) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF }; @@ -246,11 +246,11 @@ } TEST_F(SpdyHttpStreamTest, RequestInfoDestroyedBeforeRead) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, "", true)); MockRead reads[] = { @@ -308,19 +308,19 @@ } TEST_F(SpdyHttpStreamTest, LoadTimingTwoRequests) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(1, "", true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2( spdy_util_.ConstructSpdyDataFrame(3, "", true)); MockRead reads[] = { @@ -417,8 +417,8 @@ } TEST_F(SpdyHttpStreamTest, SendChunkedPost) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, kUploadData, /*fin=*/true)); @@ -427,7 +427,8 @@ CreateMockWrite(body, 1) // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3, SYNCHRONOUS), MockRead(SYNCHRONOUS, 0, 4) // EOF @@ -481,8 +482,8 @@ // This unittest tests the request callback is properly called and handled. TEST_F(SpdyHttpStreamTest, SendChunkedPostLastEmpty) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk( spdy_util_.ConstructSpdyDataFrame(1, "", true)); MockWrite writes[] = { @@ -490,7 +491,8 @@ CreateMockWrite(chunk, 1), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(chunk, 3, SYNCHRONOUS), MockRead(SYNCHRONOUS, 0, 4) // EOF @@ -538,8 +540,8 @@ } TEST_F(SpdyHttpStreamTest, ConnectionClosedDuringChunkedPost) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, kUploadData, /*fin=*/false)); @@ -548,7 +550,8 @@ CreateMockWrite(body, 1) // First POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { MockRead(ASYNC, ERR_CONNECTION_CLOSED, 2) // Server hangs up early. }; @@ -611,8 +614,8 @@ TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPost) { const char kUploadData1[] = "12345678"; const int kUploadData1Size = std::size(kUploadData1) - 1; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame chunk2( spdy_util_.ConstructSpdyDataFrame(1, kUploadData1, false)); @@ -622,7 +625,8 @@ CreateMockWrite(chunk1, 1), // POST upload frames CreateMockWrite(chunk2, 2), CreateMockWrite(chunk3, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 4), CreateMockRead(chunk1, 5), CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7), @@ -714,8 +718,8 @@ // Test that the SpdyStream state machine can handle sending a final empty data // frame when uploading a chunked data stream. TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithEmptyFinalDataFrame) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame chunk2( spdy_util_.ConstructSpdyDataFrame(1, "", true)); @@ -724,7 +728,8 @@ CreateMockWrite(chunk1, 1), // POST upload frames CreateMockWrite(chunk2, 2), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 3), CreateMockRead(chunk1, 4), CreateMockRead(chunk2, 5), MockRead(ASYNC, 0, 6) // EOF @@ -807,14 +812,15 @@ // Test that the SpdyStream state machine handles a chunked upload with no // payload. Unclear if this is a case worth supporting. TEST_F(SpdyHttpStreamTest, ChunkedPostWithEmptyPayload) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk( spdy_util_.ConstructSpdyDataFrame(1, "", true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(chunk, 1), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(chunk, 3), MockRead(ASYNC, 0, 4) // EOF @@ -886,8 +892,8 @@ MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF }; @@ -930,13 +936,14 @@ // Test the receipt of a WINDOW_UPDATE frame while waiting for a chunk to be // made available is handled correctly. TEST_F(SpdyHttpStreamTest, DelayedSendChunkedPostWithWindowUpdate) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(chunk1, 1), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame window_update( spdy_util_.ConstructSpdyWindowUpdate(1, kUploadDataSize)); MockRead reads[] = { @@ -1032,8 +1039,8 @@ } TEST_F(SpdyHttpStreamTest, DataReadErrorSynchronous) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); // Server receives spdy::ERROR_CODE_INTERNAL_ERROR on client's internal // failure. The failure is a reading error in this case caused by @@ -1046,7 +1053,8 @@ CreateMockWrite(rst_frame, 1, SYNCHRONOUS) // Reset frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), MockRead(SYNCHRONOUS, 0, 3), @@ -1089,8 +1097,8 @@ } TEST_F(SpdyHttpStreamTest, DataReadErrorAsynchronous) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); // Server receives spdy::ERROR_CODE_INTERNAL_ERROR on client's internal // failure. The failure is a reading error in this case caused by @@ -1103,7 +1111,8 @@ CreateMockWrite(rst_frame, 1) // Reset frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { MockRead(ASYNC, 0, 2), @@ -1148,8 +1157,8 @@ // Regression test for https://crbug.com/622447. TEST_F(SpdyHttpStreamTest, RequestCallbackCancelsStream) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk( spdy_util_.ConstructSpdyDataFrame(1, "", true)); spdy::SpdySerializedFrame rst(
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index dd61011..00cc0f9 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -558,12 +558,12 @@ TEST_P(SpdyNetworkTransactionTest, Get) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -582,12 +582,12 @@ TEST_P(SpdyNetworkTransactionTest, SetPriority) { for (bool set_priority_before_starting_transaction : {true, false}) { SpdyTestUtil spdy_test_util(/*use_priority_header=*/true); - spdy::SpdySerializedFrame req( - spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_test_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body( spdy_test_util.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -622,8 +622,8 @@ TEST_P(SpdyNetworkTransactionTest, SetPriorityOnExistingStream) { const char* kUrl2 = "https://www.example.org/bar"; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet(kUrl2, 3, MEDIUM)); spdy::SpdySerializedFrame priority1( spdy_util_.ConstructSpdyPriority(3, 0, MEDIUM, true)); @@ -633,10 +633,10 @@ CreateMockWrite(priority1, 4), CreateMockWrite(priority2, 5)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(resp2, 3), @@ -695,14 +695,14 @@ // First send second request on stream 1, then first request on stream 3. spdy::SpdySerializedFrame req2( spdy_util_.ConstructSpdyGet(kUrl2, 1, HIGHEST)); - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOW)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOW)); MockWrite writes[] = {CreateMockWrite(req2, 0), CreateMockWrite(req1, 1)}; - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2( spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true)); spdy::SpdySerializedFrame body1( @@ -771,8 +771,8 @@ const char* kUrl2 = "https://www.example.org/foo"; const char* kUrl3 = "https://www.example.org/bar"; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, DEFAULT_PRIORITY)); spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet(kUrl3, 3, MEDIUM)); // The headers for request 2 are set before the request is sent to SPDY and // are populated with the initial value (HIGHEST). The priority when it is @@ -784,12 +784,12 @@ CreateMockWrite(req1, 1), CreateMockWrite(req3, 2), CreateMockWrite(req2, 3)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(1, "stream 1", true)); spdy::SpdySerializedFrame body3( @@ -883,8 +883,8 @@ SpdyTestUtil spdy_test_util(/*use_priority_header=*/true); // Construct the request. - spdy::SpdySerializedFrame req( - spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, p)); + spdy::SpdySerializedFrame req(spdy_test_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, p)); MockWrite writes[] = {CreateMockWrite(req, 0)}; spdy::SpdyPriority spdy_prio = 0; @@ -915,8 +915,8 @@ FAIL(); } - spdy::SpdySerializedFrame resp( - spdy_test_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body( spdy_test_util.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { @@ -946,24 +946,24 @@ // can allow multiple streams in flight. TEST_P(SpdyNetworkTransactionTest, ThreeGets) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 5, LOWEST)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false)); spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true)); @@ -1033,17 +1033,17 @@ } TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBinding) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); @@ -1111,17 +1111,17 @@ } TEST_P(SpdyNetworkTransactionTest, TwoGetsLateBindingFromPreconnect) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); @@ -1204,26 +1204,26 @@ TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrent) { // Construct the request. // Each request fully completes before the next starts. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); spdy_util_.UpdateWithStreamDestruction(3); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 5, LOWEST)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, false)); spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(5, true)); @@ -1328,33 +1328,33 @@ // the response from the server. TEST_P(SpdyNetworkTransactionTest, FourGetsWithMaxConcurrentPriority) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); spdy_util_.UpdateWithStreamDestruction(3); - spdy::SpdySerializedFrame req4( - spdy_util_.ConstructSpdyGet(nullptr, 0, 5, HIGHEST)); - spdy::SpdySerializedFrame resp4( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame req4(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 5, HIGHEST)); + spdy::SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame fbody4(spdy_util_.ConstructSpdyDataFrame(5, true)); spdy_util_.UpdateWithStreamDestruction(5); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 7, LOWEST)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 7, LOWEST)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 7)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(7, false)); spdy::SpdySerializedFrame fbody3(spdy_util_.ConstructSpdyDataFrame(7, true)); @@ -1475,18 +1475,18 @@ // the spdy_session TEST_P(SpdyNetworkTransactionTest, ThreeGetsWithMaxConcurrentDelete) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fbody(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, false)); spdy::SpdySerializedFrame fbody2(spdy_util_.ConstructSpdyDataFrame(3, true)); @@ -1599,19 +1599,19 @@ // Construct the request. Each stream uses a different priority to provide // more useful failure information if the requests are made in an unexpected // order. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame fin_body( spdy_util_.ConstructSpdyDataFrame(1, true)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SettingsMap settings; const uint32_t max_concurrent_streams = 1; @@ -1711,8 +1711,8 @@ CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -1741,8 +1741,8 @@ CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -1760,14 +1760,16 @@ // Test that a simple POST works. TEST_P(SpdyNetworkTransactionTest, Post) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -1785,14 +1787,16 @@ // Test that a POST with a file works. TEST_P(SpdyNetworkTransactionTest, FilePost) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -1831,14 +1835,16 @@ // Test that a complex POST works. TEST_P(SpdyNetworkTransactionTest, ComplexPost) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -1856,15 +1862,16 @@ // Test that a chunked POST works. TEST_P(SpdyNetworkTransactionTest, ChunkedPost) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -1890,8 +1897,8 @@ // Test that a chunked POST works with chunks appended after transaction starts. TEST_P(SpdyNetworkTransactionTest, DelayedChunkedPost) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame chunk1(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame chunk2(spdy_util_.ConstructSpdyDataFrame(1, false)); spdy::SpdySerializedFrame chunk3(spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -1902,7 +1909,8 @@ CreateMockWrite(chunk3, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 4), CreateMockRead(chunk1, 5), CreateMockRead(chunk2, 6), CreateMockRead(chunk3, 7), @@ -1959,7 +1967,8 @@ CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -1997,7 +2006,8 @@ CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -2016,14 +2026,15 @@ // While we're doing a post, the server sends the reply before upload completes. TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostCompletes) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 3), }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), MockRead(ASYNC, 0, 4) // EOF @@ -2065,8 +2076,8 @@ // socket causes the TCP write to return zero. This test checks that the client // tries to queue up the RST_STREAM frame again. TEST_P(SpdyNetworkTransactionTest, SocketWriteReturnsZero) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); MockWrite writes[] = { @@ -2075,8 +2086,8 @@ CreateMockWrite(rst, 3, SYNCHRONOUS), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 4) // EOF }; @@ -2104,8 +2115,8 @@ CreateMockRead(body, 1), MockRead(ASYNC, 0, 3) // EOF }; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -2122,8 +2133,8 @@ // Test that the transaction doesn't crash when we get two replies on the same // stream ID. See http://crbug.com/45639. TEST_P(SpdyNetworkTransactionTest, ResponseWithTwoSynReplies) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -2131,10 +2142,10 @@ CreateMockWrite(rst, 4), }; - spdy::SpdySerializedFrame resp0( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp0(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp0, 1), CreateMockRead(resp1, 2), @@ -2168,8 +2179,8 @@ TEST_P(SpdyNetworkTransactionTest, ResetReplyWithTransferEncoding) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -2177,9 +2188,8 @@ CreateMockWrite(rst, 2), }; - const char* const headers[] = {"transfer-encoding", "chunked"}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(headers, 1, 1)); + const std::string_view headers[] = {"transfer-encoding", "chunked"}; + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply(headers, 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 3), @@ -2198,14 +2208,14 @@ TEST_P(SpdyNetworkTransactionTest, CancelledTransaction) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { CreateMockWrite(req), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp), // This following read isn't used by the test, except during the @@ -2235,8 +2245,8 @@ // Verify that the client sends a Rst Frame upon cancelling the stream. TEST_P(SpdyNetworkTransactionTest, CancelledTransactionSendRst) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); MockWrite writes[] = { @@ -2244,8 +2254,8 @@ CreateMockWrite(rst, 2, SYNCHRONOUS), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1, ASYNC), MockRead(ASYNC, nullptr, 0, 3) // EOF }; @@ -2272,8 +2282,8 @@ // to start another transaction on a session that is closing down. See // http://crbug.com/47455 TEST_P(SpdyNetworkTransactionTest, StartTransactionOnReadCallback) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req)}; MockWrite writes2[] = {CreateMockWrite(req, 0), MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -2286,8 +2296,8 @@ 0x07, 'h', 'e', 'l', 'l', 'o', '!', }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause @@ -2336,12 +2346,12 @@ // the transaction. Failures will usually be flagged by thread and/or memory // checking tools. See http://crbug.com/46925 TEST_P(SpdyNetworkTransactionTest, DeleteSessionOnReadCallback) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), @@ -2406,9 +2416,9 @@ spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); MockWrite writes0[] = {CreateMockWrite(req0, 0), CreateMockWrite(rst, 2)}; - const char* const kExtraHeaders[] = {"location", kRedirectUrl}; - spdy::SpdySerializedFrame resp0(spdy_util_.ConstructSpdyReplyError( - "301", kExtraHeaders, std::size(kExtraHeaders) / 2, 1)); + const std::string_view kExtraHeaders[] = {"location", kRedirectUrl}; + spdy::SpdySerializedFrame resp0( + spdy_util_.ConstructSpdyReplyError("301", kExtraHeaders, 1)); MockRead reads0[] = {CreateMockRead(resp0, 1), MockRead(ASYNC, 0, 3)}; SequencedSocketData data0(reads0, writes0); @@ -2427,8 +2437,8 @@ spdy_util1.ConstructSpdyHeaders(1, std::move(headers1), LOWEST, true)); MockWrite writes1[] = {CreateMockWrite(req1, 0)}; - spdy::SpdySerializedFrame resp1( - spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util1.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util1.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), MockRead(ASYNC, 0, 3)}; @@ -2467,21 +2477,20 @@ const spdy::SpdyStreamId kStreamId = 1; // Construct the request and the RST frame. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( - /*extra_headers=*/nullptr, /*extra_header_count=*/0, kStreamId, LOWEST)); + base::span<const std::string_view>(), kStreamId, LOWEST)); spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream( kStreamId, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)}; // Construct the response. - const char* const kExtraResponseHeaders[] = { + const std::string_view kExtraResponseHeaders[] = { "location", "https://example1.test", "location", "https://example2.test", }; spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyReplyError( - "301", kExtraResponseHeaders, std::size(kExtraResponseHeaders) / 2, - kStreamId)); + "301", kExtraResponseHeaders, kStreamId)); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(kStreamId, /*fin=*/true)); MockRead reads[] = { @@ -2520,8 +2529,8 @@ CreateMockWrite(req1, 2), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"), CreateMockRead(resp1, 3), CreateMockRead(body1, 4), @@ -2562,8 +2571,8 @@ CreateMockWrite(req2, 2), }; - spdy::SpdySerializedFrame resp2( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {MockRead(ASYNC, 1, "HTTP/1.1 200 OK\r\n\r\n"), CreateMockRead(resp2, 3), CreateMockRead(body2, 4), @@ -2628,8 +2637,8 @@ CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -2662,8 +2671,8 @@ CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -2745,8 +2754,8 @@ MockWrite writes1[] = { CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -2789,8 +2798,8 @@ MockWrite writes2[] = { CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -2865,11 +2874,11 @@ CreateMockWrite(req3, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads1[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), CreateMockRead(resp3, 4), CreateMockRead(body3, 5), @@ -2895,8 +2904,8 @@ CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util2.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp2, 1), CreateMockRead(body2, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -3042,11 +3051,11 @@ CreateMockWrite(req2, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), CreateMockRead(resp2, 4), CreateMockRead(body2, 5), @@ -3182,17 +3191,17 @@ CreateMockWrite(req4, 9), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true)); - spdy::SpdySerializedFrame resp4( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 7)); + spdy::SpdySerializedFrame resp4(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 7)); spdy::SpdySerializedFrame body4(spdy_util_.ConstructSpdyDataFrame(7, true)); MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), @@ -3380,18 +3389,14 @@ // Verify that various response headers parse correctly through the HTTP layer. TEST_P(SpdyNetworkTransactionTest, ResponseHeaders) { struct ResponseHeadersTests { - int extra_header_count; - const char* extra_headers[4]; + std::vector<std::string_view> extra_headers; size_t expected_header_count; std::string_view expected_headers[8]; } test_cases[] = { // No extra headers. - {0, {}, 1, {"hello", "bye"}}, + {{}, 1, {"hello", "bye"}}, // Comma-separated header value. - {1, - {"cookie", "val1, val2"}, - 2, - {"hello", "bye", "cookie", "val1, val2"}}, + {{"cookie", "val1, val2"}, 2, {"hello", "bye", "cookie", "val1, val2"}}, // Multiple headers are preserved: they are joined with \0 separator in // quiche::HttpHeaderBlock.AppendValueOrAddHeader(), then split up in // HpackEncoder, then joined with \0 separator when @@ -3399,26 +3404,24 @@ // quiche::HttpHeaderBlock.AppendValueOrAddHeader(), then split up again // in // HttpResponseHeaders. - {2, - {"content-encoding", "val1", "content-encoding", "val2"}, + {{"content-encoding", "val1", "content-encoding", "val2"}, 3, {"hello", "bye", "content-encoding", "val1", "content-encoding", "val2"}}, // Cookie header is not split up by HttpResponseHeaders. - {2, - {"cookie", "val1", "cookie", "val2"}, + {{"cookie", "val1", "cookie", "val2"}, 2, {"hello", "bye", "cookie", "val1; val2"}}}; for (size_t i = 0; i < std::size(test_cases); ++i) { SCOPED_TRACE(i); SpdyTestUtil spdy_test_util(/*use_priority_header=*/true); - spdy::SpdySerializedFrame req( - spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_test_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp(spdy_test_util.ConstructSpdyGetReply( - test_cases[i].extra_headers, test_cases[i].extra_header_count, 1)); + spdy::SpdySerializedFrame resp( + spdy_test_util.ConstructSpdyGetReply(test_cases[i].extra_headers, 1)); spdy::SpdySerializedFrame body( spdy_test_util.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { @@ -3457,19 +3460,18 @@ // Verify that we don't crash on invalid response headers. TEST_P(SpdyNetworkTransactionTest, InvalidResponseHeaders) { struct InvalidResponseHeadersTests { - int num_headers; - const char* headers[10]; + std::vector<std::string_view> headers; } test_cases[] = {// Response headers missing status header - {2, {"cookie", "val1", "cookie", "val2", nullptr}}, + {{"cookie", "val1", "cookie", "val2"}}, // Response headers with no headers - {0, {nullptr}}}; + {{}}}; for (size_t i = 0; i < std::size(test_cases); ++i) { SCOPED_TRACE(i); SpdyTestUtil spdy_test_util(/*use_priority_header=*/true); - spdy::SpdySerializedFrame req( - spdy_test_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_test_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst(spdy_test_util.ConstructSpdyRstStream( 1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -3479,8 +3481,7 @@ // Construct the reply. quiche::HttpHeaderBlock reply_headers; - AppendToHeaderBlock(test_cases[i].headers, test_cases[i].num_headers, - &reply_headers); + AppendToHeaderBlock(test_cases[i].headers, &reply_headers); spdy::SpdySerializedFrame resp( spdy_test_util.ConstructSpdyReply(1, std::move(reply_headers))); MockRead reads[] = { @@ -3497,16 +3498,16 @@ } TEST_P(SpdyNetworkTransactionTest, CorruptFrameSessionError) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_COMPRESSION_ERROR, "Framer error: 24 (HPACK_TRUNCATED_BLOCK).")); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)}; // This is the length field that's too short. - spdy::SpdySerializedFrame reply_wrong_length( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply_wrong_length(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); size_t right_size = reply_wrong_length.size() - spdy::kFrameHeaderSize; size_t wrong_size = right_size - 4; spdy::test::SetFrameLength(&reply_wrong_length, wrong_size); @@ -3524,16 +3525,16 @@ } TEST_P(SpdyNetworkTransactionTest, GoAwayOnDecompressionFailure) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_COMPRESSION_ERROR, "Framer error: 24 (HPACK_TRUNCATED_BLOCK).")); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)}; // Read HEADERS with corrupted payload. - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); memset(resp.data() + 12, 0xcf, resp.size() - 12); MockRead reads[] = {CreateMockRead(resp, 1)}; @@ -3545,8 +3546,8 @@ } TEST_P(SpdyNetworkTransactionTest, GoAwayOnFrameSizeError) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_FRAME_SIZE_ERROR, "Framer error: 9 (INVALID_CONTROL_FRAME_SIZE).")); @@ -3567,8 +3568,8 @@ // Test that we shutdown correctly on write errors. TEST_P(SpdyNetworkTransactionTest, WriteError) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { // We'll write 10 bytes successfully MockWrite(ASYNC, req.data(), 10, 1), @@ -3596,16 +3597,16 @@ // Test that partial writes work. TEST_P(SpdyNetworkTransactionTest, PartialWrite) { // Chop the HEADERS frame into 5 chunks. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); const size_t kChunks = 5u; std::unique_ptr<MockWrite[]> writes = ChopWriteFrame(req, kChunks); for (size_t i = 0; i < kChunks; ++i) { writes[i].sequence_number = i; } - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, kChunks), CreateMockRead(body, kChunks + 1), @@ -3623,16 +3624,16 @@ // Test that the NetLog contains good data for a simple GET request. TEST_P(SpdyNetworkTransactionTest, NetLog) { - static const char* const kExtraHeaders[] = { + static const std::string_view kExtraHeaders[] = { "user-agent", "Chrome", }; spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, 1, LOWEST)); + spdy_util_.ConstructSpdyGet(kExtraHeaders, 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -3729,8 +3730,8 @@ } TEST_P(SpdyNetworkTransactionTest, NetLogForResponseWithNoBody) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; quiche::HttpHeaderBlock response_headers; @@ -3773,8 +3774,8 @@ // on the network, but issued a Read for only 5 of those bytes) that the data // flow still works correctly. TEST_P(SpdyNetworkTransactionTest, BufferFull) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; // 2 data frames in a single read. @@ -3788,8 +3789,8 @@ spdy::SpdySerializedFrame last_frame( spdy_util_.ConstructSpdyDataFrame(1, "d", /*fin=*/true)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause @@ -3858,8 +3859,8 @@ // at the same time, ensure that we don't notify a read completion for // each data frame individually. TEST_P(SpdyNetworkTransactionTest, Buffering) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; // 4 data frames in a single read. @@ -3870,8 +3871,8 @@ spdy::SpdySerializedFrame combined_data_frames = CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame_fin}); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a pause @@ -3940,13 +3941,13 @@ // Verify the case where we buffer data but read it after it has been buffered. TEST_P(SpdyNetworkTransactionTest, BufferedAll) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; // 5 data frames in a single read. - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false)); spdy::SpdySerializedFrame data_frame_fin( @@ -4016,8 +4017,8 @@ // Verify the case where we buffer data and close the connection. TEST_P(SpdyNetworkTransactionTest, BufferedClosed) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; // All data frames in a single read. @@ -4026,8 +4027,8 @@ spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false)); spdy::SpdySerializedFrame combined_data_frames = CombineFrames({&data_frame, &data_frame, &data_frame, &data_frame}); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait @@ -4090,8 +4091,8 @@ // Verify the case where we buffer data and cancel the transaction. TEST_P(SpdyNetworkTransactionTest, BufferedCancelled) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 4)}; @@ -4100,8 +4101,8 @@ spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, "message", /*fin=*/false)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), // Force a wait @@ -4156,8 +4157,8 @@ // with Last-Stream-ID lower than the stream id corresponding to the request // and with error code other than NO_ERROR. TEST_P(SpdyNetworkTransactionTest, FailOnGoAway) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; spdy::SpdySerializedFrame go_away( @@ -4180,8 +4181,8 @@ NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr); // First connection. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes1[] = {CreateMockWrite(req, 0)}; spdy::SpdySerializedFrame go_away( spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_NO_ERROR, "")); @@ -4191,8 +4192,8 @@ // Second connection. MockWrite writes2[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads2[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2), MockRead(ASYNC, 0, 3)}; @@ -4213,20 +4214,20 @@ // Transactions started before receiving such a GOAWAY frame should succeed, // but SpdySession should be unavailable for new streams. TEST_P(SpdyNetworkTransactionTest, GracefulGoaway) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy_util_.UpdateWithStreamDestruction(1); spdy::SpdySerializedFrame req2( spdy_util_.ConstructSpdyGet("https://www.example.org/foo", 3, LOWEST)); MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0x7fffffff, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown.")); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), CreateMockRead(goaway, 4), CreateMockRead(resp2, 5), @@ -4307,12 +4308,12 @@ // of the incoming GOAWAY frame can receive data both before and after the // GOAWAY frame. TEST_P(SpdyNetworkTransactionTest, ActiveStreamWhileGoingAway) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( /* last_good_stream_id = */ 1, spdy::ERROR_CODE_NO_ERROR, "Graceful shutdown.")); @@ -4348,12 +4349,12 @@ } TEST_P(SpdyNetworkTransactionTest, CloseWithActiveStream) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp, 1), MockRead(SYNCHRONOUS, 0, 2) // EOF }; @@ -4602,7 +4603,8 @@ // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); MockWrite writes0[] = {CreateMockWrite(req, 0)}; spdy::SpdySerializedFrame rst( @@ -4719,7 +4721,8 @@ SpdyTestUtil spdy_util(/*use_priority_header=*/true); spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); MockWrite writes0[] = {CreateMockWrite(req, 0)}; spdy::SpdySerializedFrame rst(spdy_util.ConstructSpdyRstStream( @@ -4846,7 +4849,8 @@ // First socket: HTTP/2 CONNECT rejected with HTTP_1_1_REQUIRED. spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, kProxyServer2.host_port_pair())); MockWrite writes0[] = {CreateMockWrite(req, 0)}; spdy::SpdySerializedFrame rst( @@ -4967,18 +4971,21 @@ // CONNECT to proxy2.test:71 via SPDY. spdy::SpdySerializedFrame proxy2_connect(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, kProxyServer2.host_port_pair())); spdy::SpdySerializedFrame proxy2_connect_resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util_.ConstructSpdyGetReply(base::span<const std::string_view>(), + 1)); // Need to use a new `SpdyTestUtil()` so that the stream parent ID of this // request is calculated correctly. SpdyTestUtil new_spdy_util; // HTTP/2 endpoint CONNECT rejected with HTTP_1_1_REQUIRED. spdy::SpdySerializedFrame endpoint_connect(new_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); spdy::SpdySerializedFrame server_rst(new_spdy_util.ConstructSpdyRstStream( 1, spdy::ERROR_CODE_HTTP_1_1_REQUIRED)); @@ -5121,10 +5128,10 @@ "Proxy-Connection: keep-alive\r\n" "User-Agent: test-ua\r\n\r\n"}; const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { @@ -5179,14 +5186,14 @@ helper.RunPreTestSetup(); // Construct and send a simple GET request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -5241,8 +5248,8 @@ const char kHTTP200[] = {"HTTP/1.1 200 OK\r\n\r\n"}; spdy::SpdySerializedFrame req2( spdy_util_2.ConstructSpdyGet(kPushedUrl, 1, LOWEST)); - spdy::SpdySerializedFrame resp2( - spdy_util_2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util_2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util_2.ConstructSpdyDataFrame(1, true)); MockWrite writes2[] = { @@ -5292,8 +5299,8 @@ // This can happen when a server reboots without saying goodbye, or when // we're behind a NAT that masked the RST. TEST_P(SpdyNetworkTransactionTest, VerifyRetryOnConnectionReset) { - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), @@ -5307,13 +5314,13 @@ MockRead(ASYNC, 0, 3) // EOF }; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); // In all cases the connection will be reset before req3 can be // dispatched, destroying both streams. spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); MockWrite writes1[] = {CreateMockWrite(req, 0), CreateMockWrite(req3, 5)}; MockWrite writes2[] = {CreateMockWrite(req, 0)}; @@ -5379,15 +5386,14 @@ TEST_P(SpdyNetworkTransactionTest, SpdyBasicAuth) { // The first request will be a bare GET, the second request will be a // GET with an Authorization header. - spdy::SpdySerializedFrame req_get( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req_get(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); // Will be refused for lack of auth. spdy_util_.UpdateWithStreamDestruction(1); - const char* const kExtraAuthorizationHeaders[] = {"authorization", - "Basic Zm9vOmJhcg=="}; - spdy::SpdySerializedFrame req_get_authorization(spdy_util_.ConstructSpdyGet( - kExtraAuthorizationHeaders, std::size(kExtraAuthorizationHeaders) / 2, 3, - LOWEST)); + const std::string_view kExtraAuthorizationHeaders[] = {"authorization", + "Basic Zm9vOmJhcg=="}; + spdy::SpdySerializedFrame req_get_authorization( + spdy_util_.ConstructSpdyGet(kExtraAuthorizationHeaders, 3, LOWEST)); MockWrite spdy_writes[] = { CreateMockWrite(req_get, 0), CreateMockWrite(req_get_authorization, 3), @@ -5396,16 +5402,15 @@ // The first response is a 401 authentication challenge, and the second // response will be a 200 response since the second request includes a valid // Authorization header. - const char* const kExtraAuthenticationHeaders[] = {"www-authenticate", - "Basic realm=\"MyRealm\""}; + const std::string_view kExtraAuthenticationHeaders[] = { + "www-authenticate", "Basic realm=\"MyRealm\""}; spdy::SpdySerializedFrame resp_authentication( - spdy_util_.ConstructSpdyReplyError( - "401", kExtraAuthenticationHeaders, - std::size(kExtraAuthenticationHeaders) / 2, 1)); + spdy_util_.ConstructSpdyReplyError("401", kExtraAuthenticationHeaders, + 1)); spdy::SpdySerializedFrame body_authentication( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp_data( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp_data(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body_data( spdy_util_.ConstructSpdyDataFrame(3, true)); @@ -5460,8 +5465,8 @@ } TEST_P(SpdyNetworkTransactionTest, ResponseHeadersTwice) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -5469,8 +5474,8 @@ CreateMockWrite(rst, 4), }; - spdy::SpdySerializedFrame stream1_reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame stream1_reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); quiche::HttpHeaderBlock late_headers; late_headers["hello"] = "bye"; @@ -5495,8 +5500,8 @@ // trigger a ERR_HTTP2_PROTOCOL_ERROR because trailing HEADERS must not be // followed by any DATA frames. TEST_P(SpdyNetworkTransactionTest, SyncReplyDataAfterTrailers) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = { @@ -5504,8 +5509,8 @@ CreateMockWrite(rst, 5), }; - spdy::SpdySerializedFrame stream1_reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame stream1_reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame stream1_body( spdy_util_.ConstructSpdyDataFrame(1, false)); @@ -5531,12 +5536,12 @@ TEST_P(SpdyNetworkTransactionTest, RetryAfterRefused) { // Construct the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); // Will be destroyed by the RST before stream 3 starts. spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(req2, 2), @@ -5544,8 +5549,8 @@ spdy::SpdySerializedFrame refused( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_REFUSED_STREAM)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = { CreateMockRead(refused, 1), CreateMockRead(resp, 3), @@ -5597,13 +5602,13 @@ // req1 is alive when req2 is attempted (during but not after the // |data.RunFor(2);| statement below) but not when req3 is attempted. // The call to spdy_util_.UpdateWithStreamDestruction() reflects this. - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, HIGHEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, HIGHEST)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 5, MEDIUM)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 5, MEDIUM)); MockWrite writes[] = { MockWrite(ASYNC, ERR_IO_PENDING, 0), CreateMockWrite(req1, 1), @@ -5611,14 +5616,14 @@ CreateMockWrite(req3, 6), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true)); MockRead reads[] = { CreateMockRead(resp1, 2), MockRead(ASYNC, ERR_IO_PENDING, 3), @@ -5704,8 +5709,8 @@ static int kFrameCount = 2; std::string content(kMaxSpdyFrameChunkSize, 'a'); spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr, - 0)); + kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, content, false)); spdy::SpdySerializedFrame body_end( @@ -5723,7 +5728,8 @@ spdy_util_.ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); spdy::SpdySerializedFrame window_update_dummy( spdy_util_.ConstructSpdyWindowUpdate(2, kDeltaWindowSize)); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(window_update_dummy, 3), CreateMockRead(window_update_dummy, 4), @@ -5837,13 +5843,13 @@ std::vector<MockWrite> writes; writes.push_back(CreateMockWrite(combined_frames)); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); writes.push_back(CreateMockWrite(req, writes.size())); std::vector<MockRead> reads; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); reads.push_back(CreateMockRead(resp, writes.size() + reads.size())); std::vector<spdy::SpdySerializedFrame> body_frames; @@ -5931,8 +5937,8 @@ std::string content(kMaxSpdyFrameChunkSize, 'a'); spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, nullptr, - 0)); + kDefaultUrl, 1, kMaxSpdyFrameChunkSize * kFrameCount, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, content, false)); spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream( @@ -5995,8 +6001,8 @@ MockRead reads[] = {CreateMockRead(window_update, 1), CreateMockRead(settings_frame, 2)}; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); spdy::SpdySerializedFrame goaway( spdy_util_.ConstructSpdyGoAway(0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR, @@ -6025,8 +6031,8 @@ spdy_util_.ConstructSpdySettings(settings)); std::vector<spdy::SpdySerializedFrame> ping_frames; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); std::vector<MockWrite> writes; @@ -6098,7 +6104,7 @@ spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( kDefaultUrl, 1, /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize, - LOWEST, nullptr, 0)); + LOWEST, base::span<const std::string_view>())); // Full frames. spdy::SpdySerializedFrame body1( @@ -6168,7 +6174,7 @@ writes.push_back(CreateMockWrite(body5, i++)); spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); reads.push_back(CreateMockRead(reply, i++)); reads.push_back(CreateMockRead(body2, i++)); reads.push_back(CreateMockRead(body5, i++)); @@ -6247,7 +6253,7 @@ spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( kDefaultUrl, 1, /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize, - LOWEST, nullptr, 0)); + LOWEST, base::span<const std::string_view>())); // Full frames. spdy::SpdySerializedFrame body1( @@ -6324,7 +6330,7 @@ writes.push_back(CreateMockWrite(body5, i++)); spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); reads.push_back(CreateMockRead(reply, i++)); reads.push_back(CreateMockRead(body2, i++)); reads.push_back(CreateMockRead(body5, i++)); @@ -6408,7 +6414,7 @@ spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( kDefaultUrl, 1, /*content_length=*/kBufferSize * num_upload_buffers + kUploadDataSize, - LOWEST, nullptr, 0)); + LOWEST, base::span<const std::string_view>())); // Full frames. spdy::SpdySerializedFrame body1( @@ -6487,7 +6493,7 @@ writes.push_back(CreateMockWrite(body5, i++)); spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); reads.push_back(CreateMockRead(reply, i++)); reads.push_back(CreateMockRead(body2, i++)); reads.push_back(CreateMockRead(body5, i++)); @@ -6551,8 +6557,8 @@ spdy_util_.ConstructSpdyPushPromise(1, 2, std::move(push_headers))); MockRead reads[] = {CreateMockRead(push, 1)}; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received")); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)}; @@ -6577,8 +6583,8 @@ spdy_util_.ConstructSpdyPushPromise(1, 3, std::move(push_headers))); MockRead reads[] = {CreateMockRead(push, 1)}; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received")); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(goaway, 2)}; @@ -6610,8 +6616,8 @@ CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -6639,14 +6645,14 @@ }; // HPACK decoder implementation limits string literal length to 16 kB. - const char* response_headers[2]; + std::string_view response_headers[2]; const std::string kKey(16 * 1024, 'a'); - response_headers[0] = kKey.data(); + response_headers[0] = kKey; const std::string kValue(16 * 1024, 'b'); - response_headers[1] = kValue.data(); + response_headers[1] = kValue; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1)); + spdy_util_.ConstructSpdyGetReply(response_headers, 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -6667,15 +6673,15 @@ // End of line delimiter is forbidden according to RFC 7230 Section 3.2. TEST_P(SpdyNetworkTransactionTest, CRLFInHeaderValue) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_PROTOCOL_ERROR)); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(rst, 2)}; - const char* response_headers[] = {"folded", "foo\r\nbar"}; + const std::string_view response_headers[] = {"folded", "foo\r\nbar"}; spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(response_headers, 1, 1)); + spdy_util_.ConstructSpdyGetReply(response_headers, 1)); MockRead reads[] = {CreateMockRead(resp, 1), MockRead(ASYNC, 0, 3)}; SequencedSocketData data(reads, writes); @@ -6690,8 +6696,8 @@ // Regression test for https://crbug.com/603182. // No response headers received before RST_STREAM: error. TEST_P(SpdyNetworkTransactionTest, RstStreamNoError) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)}; spdy::SpdySerializedFrame rst( @@ -6710,11 +6716,12 @@ // Response headers and data, then RST_STREAM received, // before request body is sent: success. TEST_P(SpdyNetworkTransactionTest, RstStreamNoErrorAfterResponse) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); MockWrite writes[] = {CreateMockWrite(req, 0, ASYNC)}; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR)); @@ -6732,16 +6739,16 @@ } TEST_P(SpdyNetworkTransactionTest, 100Continue) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; quiche::HttpHeaderBlock informational_headers; informational_headers[spdy::kHttp2StatusHeader] = "100"; spdy::SpdySerializedFrame informational_response( spdy_util_.ConstructSpdyReply(1, std::move(informational_headers))); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(informational_response, 1), CreateMockRead(resp, 2), @@ -6764,11 +6771,12 @@ // data are sent and closes connection: this must result in // ERR_CONNECTION_CLOSED (as opposed to ERR_HTTP2_PROTOCOL_ERROR). TEST_P(SpdyNetworkTransactionTest, ResponseBeforePostDataSent) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2), MockRead(ASYNC, 0, 3)}; @@ -6788,11 +6796,12 @@ // Regression test for https://crbug.com/606990. // Server responds before POST data are sent and resets stream with NO_ERROR. TEST_P(SpdyNetworkTransactionTest, ResponseAndRstStreamBeforePostDataSent) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_NO_ERROR)); @@ -6816,8 +6825,8 @@ // but is going to be used for the ORIGIN frame. // TODO(bnc): Implement ORIGIN frame support. https://crbug.com/697333 TEST_P(SpdyNetworkTransactionTest, IgnoreUnsupportedOriginFrame) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; const char origin_frame_on_stream_zero[] = { @@ -6838,8 +6847,8 @@ 'b', 'a', 'r' // ASCII-Origin }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {MockRead(ASYNC, origin_frame_on_stream_zero, std::size(origin_frame_on_stream_zero), 1), @@ -6925,12 +6934,12 @@ } TEST_P(SpdyNetworkTransactionTest, RequestHeadersCallback) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, DEFAULT_PRIORITY)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -6964,12 +6973,12 @@ helper.RunPreTestSetup(); // First request opens up an HTTP/2 connection. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, DEFAULT_PRIORITY)); MockWrite writes1[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads1[] = {CreateMockRead(resp, 1), CreateMockRead(body, 2), MockRead(ASYNC, ERR_IO_PENDING, 3), @@ -7084,13 +7093,13 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {CreateMockRead(resp1, 1), CreateMockRead(body1, 2), MockRead(SYNCHRONOUS, ERR_IO_PENDING, 3)}; @@ -7202,8 +7211,8 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); quiche::HttpHeaderBlock websocket_request_headers; @@ -7233,11 +7242,11 @@ settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; spdy::SpdySerializedFrame settings_frame( spdy_util_.ConstructSpdySettings(settings)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame websocket_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame websocket_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead reads[] = {CreateMockRead(settings_frame, 1), CreateMockRead(resp1, 3), CreateMockRead(body1, 7), CreateMockRead(websocket_response, 8), @@ -7334,8 +7343,8 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); MockWrite writes[] = {MockWrite(SYNCHRONOUS, 0, "CONNECT www.example.org:443 HTTP/1.1\r\n" @@ -7344,8 +7353,8 @@ "User-Agent: test-ua\r\n\r\n"), CreateMockWrite(req, 2)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {MockRead(SYNCHRONOUS, 1, "HTTP/1.1 200 OK\r\n\r\n"), CreateMockRead(resp1, 3), CreateMockRead(body1, 4), @@ -7481,8 +7490,8 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); quiche::HttpHeaderBlock websocket_request_headers; @@ -7512,11 +7521,11 @@ settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; spdy::SpdySerializedFrame settings_frame( spdy_util_.ConstructSpdySettings(settings)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame websocket_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame websocket_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead reads[] = {CreateMockRead(settings_frame, 1), CreateMockRead(resp1, 3), CreateMockRead(body1, 7), CreateMockRead(websocket_response, 8), @@ -7633,8 +7642,8 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); MockWrite writes[] = {CreateMockWrite(req, 0), @@ -7644,8 +7653,8 @@ settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; spdy::SpdySerializedFrame settings_frame( spdy_util_.ConstructSpdySettings(settings)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {CreateMockRead(settings_frame, 1), CreateMockRead(resp1, 3), CreateMockRead(body1, 4), @@ -7816,8 +7825,8 @@ std::move(session_deps)); helper.RunPreTestSetup(); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); quiche::HttpHeaderBlock websocket_request_headers; @@ -7846,8 +7855,8 @@ settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; spdy::SpdySerializedFrame settings_frame( spdy_util_.ConstructSpdySettings(settings)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame websocket_response_http11_required( spdy_util_.ConstructSpdyRstStream(3, spdy::ERROR_CODE_HTTP_1_1_REQUIRED)); @@ -7938,7 +7947,8 @@ // should work for HTTP/2 proxies. TEST_P(SpdyNetworkTransactionTest, PlaintextWebSocketOverHttp2Proxy) { spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 80))); const char kWebSocketRequest[] = "GET / HTTP/1.1\r\n" @@ -7955,8 +7965,8 @@ MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(websocket_request, 2)}; - spdy::SpdySerializedFrame connect_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); const char kWebSocketResponse[] = "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" @@ -8004,13 +8014,14 @@ // Connect request to the origin using HTTP/2. spdy::SpdySerializedFrame connect_request( proxy_spdy_util.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); // Requests through the proxy are wrapped in DATA frames on the proxy's // stream ID 1. - spdy::SpdySerializedFrame req( - origin_spdy_util.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(origin_spdy_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); spdy::SpdySerializedFrame wrapped_req( proxy_spdy_util.ConstructSpdyDataFrame(1, req, false)); spdy::SpdySerializedFrame settings_ack( @@ -8041,7 +8052,8 @@ CreateMockWrite(wrapped_websocket_request, 6)}; spdy::SpdySerializedFrame connect_response( - proxy_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + proxy_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SettingsMap settings; settings[spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL] = 1; @@ -8049,8 +8061,8 @@ origin_spdy_util.ConstructSpdySettings(settings)); spdy::SpdySerializedFrame wrapped_settings_frame( proxy_spdy_util.ConstructSpdyDataFrame(1, settings_frame, false)); - spdy::SpdySerializedFrame resp1( - origin_spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(origin_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame wrapped_resp1( proxy_spdy_util.ConstructSpdyDataFrame(1, resp1, false)); spdy::SpdySerializedFrame body1( @@ -8058,7 +8070,8 @@ spdy::SpdySerializedFrame wrapped_body1( proxy_spdy_util.ConstructSpdyDataFrame(1, body1, false)); spdy::SpdySerializedFrame websocket_response( - origin_spdy_util.ConstructSpdyGetReply(nullptr, 0, 3)); + origin_spdy_util.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame wrapped_websocket_response( proxy_spdy_util.ConstructSpdyDataFrame(1, websocket_response, false)); @@ -8159,7 +8172,8 @@ TEST_P(SpdyNetworkTransactionTest, SecureWebSocketOverHttp2Proxy) { spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); const char kWebSocketRequest[] = "GET / HTTP/1.1\r\n" @@ -8176,8 +8190,8 @@ MockWrite writes[] = {CreateMockWrite(connect_request, 0), CreateMockWrite(websocket_request, 2)}; - spdy::SpdySerializedFrame connect_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); const char kWebSocketResponse[] = "HTTP/1.1 101 Switching Protocols\r\n" "Upgrade: websocket\r\n" @@ -8241,11 +8255,12 @@ TEST_P(SpdyNetworkTransactionTest, SecureWebSocketOverHttp2ProxyNegotiatesHttp2) { spdy::SpdySerializedFrame connect_request(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); MockWrite writes[] = {CreateMockWrite(connect_request, 0)}; - spdy::SpdySerializedFrame connect_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = {CreateMockRead(connect_response, 1), MockRead(ASYNC, 0, 2)}; SequencedSocketData data(reads, writes); @@ -8292,12 +8307,12 @@ TEST_P(SpdyNetworkTransactionTest, ZeroRTTDoesntConfirm) { static const base::TimeDelta kDelay = base::Milliseconds(10); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2), @@ -8334,17 +8349,17 @@ // Run multiple concurrent streams that don't require handshake confirmation. TEST_P(SpdyNetworkTransactionTest, ZeroRTTNoConfirmMultipleStreams) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); MockWrite writes1[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 3)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads1[] = { CreateMockRead(resp1, 1), CreateMockRead(body1, 2), @@ -8402,11 +8417,11 @@ CreateMockWrite(req1, 0), CreateMockWrite(req2, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = { CreateMockRead(resp1, 1), CreateMockRead(body1, 2), @@ -8490,11 +8505,11 @@ CreateMockWrite(req1, 0), CreateMockWrite(req2, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = { CreateMockRead(resp1, 1), CreateMockRead(body1, 2), @@ -8581,11 +8596,11 @@ CreateMockWrite(req1, 0), CreateMockWrite(req2, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = { CreateMockRead(resp1, 1), CreateMockRead(body1, 2), @@ -8657,15 +8672,17 @@ TEST_P(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmSyncWrite) { static const base::TimeDelta kDelay = base::Milliseconds(10); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0, SYNCHRONOUS), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8701,15 +8718,17 @@ } TEST_P(SpdyNetworkTransactionTest, ZeroRTTSyncConfirmAsyncWrite) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0, ASYNC), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8732,15 +8751,17 @@ TEST_P(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmSyncWrite) { static const base::TimeDelta kDelay = base::Milliseconds(10); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0, SYNCHRONOUS), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8775,15 +8796,17 @@ } TEST_P(SpdyNetworkTransactionTest, ZeroRTTAsyncConfirmAsyncWrite) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0, ASYNC), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8805,14 +8828,16 @@ } TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorSync) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8834,14 +8859,16 @@ } TEST_P(SpdyNetworkTransactionTest, ZeroRTTConfirmErrorAsync) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF @@ -8944,12 +8971,12 @@ NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, std::move(session_deps)); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, DEFAULT_PRIORITY)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, DEFAULT_PRIORITY)); MockWrite writes[] = {CreateMockWrite(req, 0)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -9008,8 +9035,8 @@ MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1), CreateMockWrite(empty_body, 2)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -9048,8 +9075,9 @@ NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, std::move(session_deps)); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); uint8_t kRawFrameData[] = { 0x00, 0x00, 0x03, // length @@ -9066,8 +9094,8 @@ MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1), CreateMockWrite(request_body, 2)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -9107,8 +9135,9 @@ NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, std::move(session_deps)); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kUploadDataSize, LOWEST, + base::span<const std::string_view>())); uint8_t kRawFrameData[] = { 0x00, 0x00, 0x03, // length @@ -9125,8 +9154,8 @@ MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(grease, 1), CreateMockWrite(request_body, 2)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -9169,10 +9198,11 @@ // CONNECT to proxy. spdy::SpdySerializedFrame connect_req(spdy_util_.ConstructSpdyConnect( - nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + HttpProxyConnectJob::kH2QuicTunnelPriority, HostPortPair("www.example.org", 443))); - spdy::SpdySerializedFrame connect_response( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_response(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Tunneled transaction wrapped in DATA frames. const char req[] = @@ -9270,8 +9300,8 @@ CreateMockWrite(req, 0), MockWrite(ASYNC, ERR_IO_PENDING, 2), CreateMockWrite(grease, 3), CreateMockWrite(empty_body, 4)}; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame response_body( spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -9296,13 +9326,14 @@ } TEST_P(SpdyNetworkTransactionTest, NotAllowHTTP1NotBlockH2Post) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructChunkedSpdyPost(nullptr, 0)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructChunkedSpdyPost( + base::span<const std::string_view>())); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), // POST upload frame }; - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); MockRead reads[] = { CreateMockRead(resp, 2), CreateMockRead(body, 3), MockRead(ASYNC, 0, 4) // EOF
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index 009cfaa..4de22f6b 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -1487,8 +1487,8 @@ SpdyTestUtil spdy_util; - spdy::SpdySerializedFrame req( - spdy_util.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame settings_ack(spdy_util.ConstructSpdySettingsAck()); MockWrite writes[] = {CreateMockWrite(req, 0), CreateMockWrite(settings_ack, 2)}; @@ -1498,7 +1498,7 @@ spdy::SpdySerializedFrame settings_frame( spdy_util.ConstructSpdySettings(settings)); spdy::SpdySerializedFrame resp( - spdy_util.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy_util.ConstructSpdyGetReply(base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util.ConstructSpdyDataFrame(1, true)); MockRead reads[] = {CreateMockRead(settings_frame, 1), CreateMockRead(resp, 3), CreateMockRead(body, 4), @@ -1924,8 +1924,8 @@ spdy::SpdySerializedFrame settings_frame = spdy_util.ConstructSpdySettings(settings); spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck(); - spdy::SpdySerializedFrame req( - spdy_util.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); const MockConnect connect_data(SYNCHRONOUS, OK); const MockRead reads[] = {
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index 9c9e637..ae0952b 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -530,10 +530,10 @@ MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3), MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; @@ -601,8 +601,8 @@ }; // No |req2|, because the second stream will never get activated. - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -659,10 +659,10 @@ MockRead(ASYNC, ERR_IO_PENDING, 4), CreateMockRead(goaway2, 5), MockRead(ASYNC, ERR_IO_PENDING, 6), MockRead(ASYNC, 0, 7) // EOF }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; @@ -727,10 +727,10 @@ MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3), MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; @@ -791,14 +791,14 @@ // then processes a GOAWAY. The session should gracefully drain. Regression test // for crbug.com/379469 TEST_F(SpdySessionTest, GoAwayWhileDraining) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); size_t joint_size = goaway.size() * 2 + body.size(); @@ -858,19 +858,19 @@ const int kStreamId1 = 1; const int kStreamId2 = 3; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, kStreamId1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, kStreamId2, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), kStreamId1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), kStreamId2, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, kStreamId1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, kStreamId2)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), kStreamId1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), kStreamId2)); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(kStreamId1, true)); @@ -945,8 +945,8 @@ MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(goaway, 2), MockRead(ASYNC, ERR_IO_PENDING, 3), MockRead(ASYNC, 0, 4) // EOF }; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req, 0), }; @@ -1004,8 +1004,8 @@ MockRead(ASYNC, ERR_IO_PENDING, 3), CreateMockRead(push, 4), MockRead(ASYNC, 0, 6) // EOF }; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); spdy::SpdySerializedFrame goaway_sent(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_PROTOCOL_ERROR, "PUSH_PROMISE received")); MockWrite writes[] = {CreateMockWrite(req, 0), @@ -1054,8 +1054,8 @@ MockRead reads[] = { MockRead(ASYNC, ERR_IO_PENDING, 1), MockRead(ASYNC, 0, 2) // EOF }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -1227,8 +1227,8 @@ session_deps_.time_func = TheNearFuture; spdy::SpdySerializedFrame write_ping(spdy_util_.ConstructSpdyPing(1, false)); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(write_ping, 1), }; @@ -1367,19 +1367,19 @@ // stalled streams are aborted. Also verify the activated streams complete, // at which point the session closes. - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId - 2, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, kLastStreamId, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), kLastStreamId - 2, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), kLastStreamId, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, kLastStreamId - 2)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, kLastStreamId)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), kLastStreamId - 2)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), kLastStreamId)); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(kLastStreamId - 2, true)); @@ -1499,11 +1499,11 @@ spdy_util_.ConstructSpdySettingsAck()); // Request and response. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); @@ -2071,8 +2071,8 @@ } TEST_F(SpdySessionTest, HeadersCompressionHistograms) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req, 0), }; @@ -2117,20 +2117,20 @@ // first. TEST_F(SpdySessionTest, OutOfOrderHeaders) { // Construct the request. - spdy::SpdySerializedFrame req_highest( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); - spdy::SpdySerializedFrame req_lowest( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req_highest(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); + spdy::SpdySerializedFrame req_lowest(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); MockWrite writes[] = { CreateMockWrite(req_highest, 0), CreateMockWrite(req_lowest, 1), }; - spdy::SpdySerializedFrame resp_highest( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp_highest(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body_highest( spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp_lowest( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp_lowest(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body_lowest( spdy_util_.ConstructSpdyDataFrame(3, true)); MockRead reads[] = { @@ -2186,14 +2186,14 @@ TEST_F(SpdySessionTest, CancelStream) { // Request 1, at HIGHEST priority, will be cancelled before it writes data. // Request 2, at LOWEST priority, will be a full request and will be id 1. - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); MockWrite writes[] = { CreateMockWrite(req2, 0), }; - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp2, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), @@ -2370,10 +2370,10 @@ // Create two streams that are set to re-close themselves on close, // activate them, and then close the session. Nothing should blow up. TEST_F(SpdySessionTest, CloseSessionWithTwoActivatedSelfClosingStreams) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; @@ -2443,10 +2443,10 @@ // Create two streams that are set to close each other on close, // activate them, and then close the session. Nothing should blow up. TEST_F(SpdySessionTest, CloseSessionWithTwoActivatedMutuallyClosingStreams) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), }; @@ -2536,8 +2536,8 @@ // Close an activated stream that closes its session. Nothing should // blow up. This is a regression test for https://crbug.com/263691. TEST_F(SpdySessionTest, CloseActivatedStreamThatClosesSession) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); spdy::SpdySerializedFrame rst( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( @@ -2617,14 +2617,14 @@ new_settings[kSpdySettingsId1] = max_concurrent_streams; spdy::SpdySerializedFrame settings_ack(spdy_util_.ConstructSpdySettingsAck()); - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy_util_.UpdateWithStreamDestruction(1); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, LOWEST)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, LOWEST)); spdy_util_.UpdateWithStreamDestruction(3); - spdy::SpdySerializedFrame req3( - spdy_util_.ConstructSpdyGet(nullptr, 0, 5, LOWEST)); + spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 5, LOWEST)); MockWrite writes[] = { CreateMockWrite(settings_ack, 1), CreateMockWrite(req1, 2), CreateMockWrite(req2, 5), CreateMockWrite(req3, 8), @@ -2635,16 +2635,16 @@ spdy::SpdySerializedFrame settings_frame( spdy_util_.ConstructSpdySettings(new_settings)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); spdy::SpdySerializedFrame body2(spdy_util_.ConstructSpdyDataFrame(3, true)); - spdy::SpdySerializedFrame resp3( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 5)); + spdy::SpdySerializedFrame resp3(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 5)); spdy::SpdySerializedFrame body3(spdy_util_.ConstructSpdyDataFrame(5, true)); MockRead reads[] = { @@ -2847,8 +2847,8 @@ TEST_F(SpdySessionTest, ReadDataWithoutYielding) { session_deps_.time_func = InstantaneousReads; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -2864,8 +2864,8 @@ spdy::SpdySerializedFrame finish_data_frame(spdy_util_.ConstructSpdyDataFrame( 1, std::string_view(payload).substr(kPayloadSize - 1), /*fin=*/true)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Write 1 byte less than kMaxReadBytes to check that DoRead reads up to 32k // bytes. @@ -2929,14 +2929,14 @@ TEST_F(SpdySessionTest, TestYieldingSlowReads) { session_deps_.time_func = SlowReads; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp1, 1), MockRead(ASYNC, 0, 2) // EOF @@ -2989,8 +2989,8 @@ TEST_F(SpdySessionTest, TestYieldingSlowSynchronousReads) { session_deps_.time_func = SlowReads; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -3000,8 +3000,8 @@ spdy::SpdySerializedFrame finish_data_frame( spdy_util_.ConstructSpdyDataFrame(1, "bar", /*fin=*/true)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp1, 1), @@ -3057,8 +3057,8 @@ TEST_F(SpdySessionTest, TestYieldingDuringReadData) { session_deps_.time_func = InstantaneousReads; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -3074,8 +3074,8 @@ spdy::SpdySerializedFrame finish_data_frame( spdy_util_.ConstructSpdyDataFrame(1, "h", /*fin=*/true)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Write 1 byte more than kMaxReadBytes to check that DoRead yields. MockRead reads[] = { @@ -3146,8 +3146,8 @@ TEST_F(SpdySessionTest, TestYieldingDuringAsyncReadData) { session_deps_.time_func = InstantaneousReads; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; @@ -3170,8 +3170,8 @@ spdy::SpdySerializedFrame finish_data_frame( spdy_util_.ConstructSpdyDataFrame(1, "h", /*fin=*/true)); - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { CreateMockRead(resp1, 1), @@ -3237,14 +3237,14 @@ // Send a GoAway frame when SpdySession is in DoReadLoop. Make sure // nothing blows up. TEST_F(SpdySessionTest, GoAwayWhileInDoReadLoop) { - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body1(spdy_util_.ConstructSpdyDataFrame(1, true)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway(0)); @@ -3485,8 +3485,8 @@ MockRead reads[] = { MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever. }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame cancel1( spdy_util_.ConstructSpdyRstStream(1, spdy::ERROR_CODE_CANCEL)); MockWrite writes[] = { @@ -3632,8 +3632,8 @@ // should blow up. This is a regression test for // http://crbug.com/263690 . TEST_F(SpdySessionTest, CreateStreamOnStreamReset) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req, 0), }; @@ -3946,16 +3946,16 @@ const int32_t stream_max_recv_window_size = 1024; const int32_t data_frame_size = 2 * stream_max_recv_window_size; - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream( 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(rst, 4), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); const std::string payload(data_frame_size, 'a'); spdy::SpdySerializedFrame data_frame( spdy_util_.ConstructSpdyDataFrame(1, payload, false)); @@ -4079,16 +4079,16 @@ ASSERT_LT(stream_max_recv_window_size, first_data_frame_size + second_data_frame_size); - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame rst(spdy_util_.ConstructSpdyRstStream( 1, spdy::ERROR_CODE_FLOW_CONTROL_ERROR)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(rst, 6), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); const std::string first_data_frame(first_data_frame_size, 'a'); spdy::SpdySerializedFrame first( spdy_util_.ConstructSpdyDataFrame(1, first_data_frame, false)); @@ -4173,16 +4173,17 @@ const int32_t kMsgDataSize = 100; const std::string msg_data(kMsgDataSize, 'a'); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kMsgDataSize, MEDIUM, + base::span<const std::string_view>())); spdy::SpdySerializedFrame msg( spdy_util_.ConstructSpdyDataFrame(1, msg_data, false)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(msg, 2), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame echo( spdy_util_.ConstructSpdyDataFrame(1, msg_data, false)); spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate( @@ -4244,14 +4245,15 @@ const int32_t kMsgDataSize = 100; const std::string msg_data(kMsgDataSize, 'a'); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kMsgDataSize, MEDIUM, + base::span<const std::string_view>())); MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); MockRead reads[] = { MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2), MockRead(ASYNC, 0, 3) // EOF @@ -4315,16 +4317,17 @@ const int32_t kMsgDataSize = 100; const std::string msg_data(kMsgDataSize, 'a'); - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kMsgDataSize, MEDIUM, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kMsgDataSize, MEDIUM, + base::span<const std::string_view>())); spdy::SpdySerializedFrame msg( spdy_util_.ConstructSpdyDataFrame(1, msg_data, false)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(msg, 2), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame echo( spdy_util_.ConstructSpdyDataFrame(1, msg_data, false)); spdy::SpdySerializedFrame window_update(spdy_util_.ConstructSpdyWindowUpdate( @@ -4417,16 +4420,17 @@ void SpdySessionTest::RunResumeAfterUnstallTest( base::OnceCallback<void(SpdyStream*)> stall_function, base::OnceCallback<void(SpdyStream*, int32_t)> unstall_function) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, true)); MockWrite writes[] = { CreateMockWrite(req, 0), CreateMockWrite(body, 1), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame echo( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, false)); MockRead reads[] = { @@ -4535,10 +4539,12 @@ // streams should resume in priority order when that window is then // increased. TEST_F(SpdySessionTest, ResumeByPriorityAfterSendWindowSizeIncrease) { - spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0)); - spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 3, kBodyDataSize, MEDIUM, nullptr, 0)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 3, kBodyDataSize, MEDIUM, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, true)); spdy::SpdySerializedFrame body2( @@ -4548,10 +4554,10 @@ CreateMockWrite(body2, 2), CreateMockWrite(body1, 3), }; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead reads[] = { CreateMockRead(resp1, 4), CreateMockRead(resp2, 5), MockRead(ASYNC, 0, 6) // EOF @@ -4645,10 +4651,12 @@ // is stalled again when the stream gets unstalled. The stream should not fail. // Regression test for https://crbug.com/761919. TEST_F(SpdySessionTest, ResumeSessionWithStalledStream) { - spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0)); - spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 3, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(3, kBodyDataStringPiece, true)); spdy::SpdySerializedFrame body2( @@ -4656,10 +4664,10 @@ MockWrite writes[] = {CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), CreateMockWrite(body1, 2), CreateMockWrite(body2, 3)}; - spdy::SpdySerializedFrame resp1( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp1(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead reads[] = {CreateMockRead(resp1, 4), CreateMockRead(resp2, 5), MockRead(ASYNC, 0, 6)}; @@ -4908,10 +4916,10 @@ MockRead(ASYNC, ERR_IO_PENDING, 2), CreateMockRead(goaway, 3), MockRead(ASYNC, ERR_IO_PENDING, 4), MockRead(ASYNC, 0, 5) // EOF }; - spdy::SpdySerializedFrame req1( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, MEDIUM)); - spdy::SpdySerializedFrame req2( - spdy_util_.ConstructSpdyGet(nullptr, 0, 3, MEDIUM)); + spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, MEDIUM)); + spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 3, MEDIUM)); MockWrite writes[] = { CreateMockWrite(req1, 0), CreateMockWrite(req2, 1), @@ -5005,12 +5013,15 @@ // Cause a stall by reducing the flow control send window to // 0. Unstalling the session should properly handle deleted streams. TEST_F(SpdySessionTest, SendWindowSizeIncreaseWithDeletedStreams) { - spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0)); - spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0)); - spdy::SpdySerializedFrame req3(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 5, kBodyDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 3, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); + spdy::SpdySerializedFrame req3( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 5, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body2( spdy_util_.ConstructSpdyDataFrame(3, kBodyDataStringPiece, true)); MockWrite writes[] = { @@ -5018,8 +5029,8 @@ CreateMockWrite(req3, 2), CreateMockWrite(body2, 3), }; - spdy::SpdySerializedFrame resp2( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame resp2(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); MockRead reads[] = { CreateMockRead(resp2, 4), MockRead(ASYNC, ERR_IO_PENDING, 5), MockRead(ASYNC, 0, 6) // EOF @@ -5143,10 +5154,12 @@ // 0. Unstalling the session should properly handle the session itself // being closed. TEST_F(SpdySessionTest, SendWindowSizeIncreaseWithDeletedSession) { - spdy::SpdySerializedFrame req1(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kBodyDataSize, LOWEST, nullptr, 0)); - spdy::SpdySerializedFrame req2(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 3, kBodyDataSize, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req1( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); + spdy::SpdySerializedFrame req2( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 3, kBodyDataSize, LOWEST, + base::span<const std::string_view>())); spdy::SpdySerializedFrame body1( spdy_util_.ConstructSpdyDataFrame(1, kBodyDataStringPiece, false)); MockWrite writes[] = { @@ -5233,8 +5246,8 @@ } TEST_F(SpdySessionTest, GoAwayOnSessionFlowControlError) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); spdy::SpdySerializedFrame goaway(spdy_util_.ConstructSpdyGoAway( 0, spdy::ERROR_CODE_FLOW_CONTROL_ERROR, "delta_window_size is 6 in DecreaseRecvWindowSize, which is larger than " @@ -5243,8 +5256,8 @@ CreateMockWrite(req, 0), CreateMockWrite(goaway, 4), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { MockRead(ASYNC, ERR_IO_PENDING, 1), CreateMockRead(resp, 2), @@ -5507,14 +5520,14 @@ // Tests basic functionality of ReadIfReady() when it is enabled or disabled. TEST_P(SpdySessionReadIfReadyTest, ReadIfReady) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, HIGHEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, HIGHEST)); MockWrite writes[] = { CreateMockWrite(req, 0), }; - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame body(spdy_util_.ConstructSpdyDataFrame(1, true)); MockRead reads[] = { CreateMockRead(resp, 1), CreateMockRead(body, 2),
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index eb4697f..b90ceb5 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc
@@ -170,11 +170,13 @@ }; TEST_F(SpdyStreamTest, SendDataAfterOpen) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); AddRead(resp); spdy::SpdySerializedFrame msg( @@ -219,11 +221,13 @@ } TEST_F(SpdyStreamTest, BrokenConnectionDetectionSuccessfulRequest) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); AddRead(resp); spdy::SpdySerializedFrame msg( @@ -289,15 +293,17 @@ // Regression test for https://crbug.com/481033. TEST_F(SpdyStreamTest, Trailers) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); spdy::SpdySerializedFrame msg( spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true)); AddWrite(msg); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); AddRead(resp); spdy::SpdySerializedFrame echo( @@ -347,12 +353,13 @@ } TEST_F(SpdyStreamTest, StreamError) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(resp); spdy::SpdySerializedFrame msg( @@ -415,8 +422,9 @@ // Make sure that large blocks of data are properly split up into frame-sized // chunks for a request/response (i.e., an HTTP-like) stream. TEST_F(SpdyStreamTest, SendLargeDataAfterOpenRequestResponse) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); @@ -429,7 +437,8 @@ spdy_util_.ConstructSpdyDataFrame(1, chunk_data, true)); AddWrite(last_chunk); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); AddRead(resp); AddReadEOF(); @@ -468,11 +477,13 @@ // Make sure that large blocks of data are properly split up into frame-sized // chunks for a bidirectional (i.e., non-HTTP-like) stream. TEST_F(SpdyStreamTest, SendLargeDataAfterOpenBidirectional) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); - spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyPostReply(nullptr, 0)); + spdy::SpdySerializedFrame resp( + spdy_util_.ConstructSpdyPostReply(base::span<const std::string_view>())); AddRead(resp); std::string chunk_data(kMaxSpdyFrameChunkSize, 'x'); @@ -517,13 +528,13 @@ // Receiving a header with uppercase ASCII should result in a protocol error. TEST_F(SpdyStreamTest, UpperCaseHeaders) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); - const char* const kExtraHeaders[] = {"X-UpperCase", "yes"}; - spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( - kExtraHeaders, std::size(kExtraHeaders) / 2, 1)); + const std::string_view kExtraHeaders[] = {"X-UpperCase", "yes"}; + spdy::SpdySerializedFrame reply( + spdy_util_.ConstructSpdyGetReply(kExtraHeaders, 1)); AddRead(reply); spdy::SpdySerializedFrame rst( @@ -565,8 +576,8 @@ } TEST_F(SpdyStreamTest, HeadersMustHaveStatus) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); // Response headers without ":status" header field: protocol error. @@ -617,12 +628,12 @@ } TEST_F(SpdyStreamTest, TrailersMustNotFollowTrailers) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); spdy::SpdySerializedFrame body( @@ -680,12 +691,12 @@ } TEST_F(SpdyStreamTest, DataMustNotFollowTrailers) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); spdy::SpdySerializedFrame body( @@ -789,13 +800,13 @@ // Test that the response start time is recorded for non-informational response. TEST_F(SpdyStreamTestWithMockClock, NonInformationalResponseStart) { // Set up the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); // Set up the response headers. - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); // Separate the headers into 2 fragments and add pauses between the fragments // so that the test runner can advance the mock clock to test timing // information. @@ -852,8 +863,8 @@ TEST_F(SpdyStreamTestWithMockClock, InformationalHeaders) { // Set up the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); // Set up the informational response headers. @@ -871,8 +882,8 @@ AddReadPause(); // Set up the non-informational response headers and body. - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); AddReadPause(); spdy::SpdySerializedFrame body( @@ -941,8 +952,8 @@ // callbacks are called as expected. TEST_F(SpdyStreamTestWithMockClock, EarlyHints) { // Set up the request. - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); // Set up two early hints response headers. @@ -979,8 +990,8 @@ AddReadPause(); // Set up the non-informational response headers and body. - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); AddReadPause(); spdy::SpdySerializedFrame body( @@ -1078,8 +1089,8 @@ } TEST_F(SpdyStreamTest, StatusMustBeNumber) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); quiche::HttpHeaderBlock incorrect_headers; @@ -1126,8 +1137,8 @@ } TEST_F(SpdyStreamTest, StatusCannotHaveExtraText) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); quiche::HttpHeaderBlock headers_with_status_text; @@ -1179,8 +1190,8 @@ } TEST_F(SpdyStreamTest, StatusMustBePresent) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); quiche::HttpHeaderBlock headers_without_status; @@ -1232,8 +1243,9 @@ // Call IncreaseSendWindowSize on a stream with a large enough delta to overflow // an int32_t. The SpdyStream should handle that case gracefully. TEST_F(SpdyStreamTest, IncreaseSendWindowSizeOverflow) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); AddReadPause(); @@ -1319,16 +1331,17 @@ // and unstall. void SpdyStreamTest::RunResumeAfterUnstallRequestResponseTest( UnstallFunction unstall_function) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); spdy::SpdySerializedFrame body( spdy_util_.ConstructSpdyDataFrame(1, kPostBodyStringPiece, true)); AddWrite(body); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(resp); AddReadEOF(); @@ -1389,14 +1402,15 @@ // (i.e., non-HTTP-like) stream resumes after a stall and unstall. void SpdyStreamTest::RunResumeAfterUnstallBidirectionalTest( UnstallFunction unstall_function) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); AddReadPause(); - spdy::SpdySerializedFrame resp( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame resp(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(resp); spdy::SpdySerializedFrame msg( @@ -1467,14 +1481,14 @@ // Test calculation of amount of bytes received from network. TEST_F(SpdyStreamTest, ReceivedBytes) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); AddReadPause(); - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); AddReadPause(); @@ -1538,8 +1552,9 @@ // Regression test for https://crbug.com/810763. TEST_F(SpdyStreamTest, DataOnHalfClosedRemoveStream) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); quiche::HttpHeaderBlock response_headers; @@ -1589,8 +1604,9 @@ } TEST_F(SpdyStreamTest, DelegateIsInformedOfEOF) { - spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost( - kDefaultUrl, 1, kPostBodyLength, LOWEST, nullptr, 0)); + spdy::SpdySerializedFrame req( + spdy_util_.ConstructSpdyPost(kDefaultUrl, 1, kPostBodyLength, LOWEST, + base::span<const std::string_view>())); AddWrite(req); quiche::HttpHeaderBlock response_headers; @@ -1643,14 +1659,14 @@ // count of unacknowledged bytes to zero only after // kDefaultTimeToBufferSmallWindowUpdates time has passed. TEST_F(SpdyStreamTestWithMockClock, FlowControlSlowReads) { - spdy::SpdySerializedFrame req( - spdy_util_.ConstructSpdyGet(nullptr, 0, 1, LOWEST)); + spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyGet( + base::span<const std::string_view>(), 1, LOWEST)); AddWrite(req); AddReadPause(); - spdy::SpdySerializedFrame reply( - spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame reply(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(reply); AddReadPause();
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index b17b533..0dd996bd 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -112,22 +112,22 @@ // where the even entries are the header names, and the odd entries are the // header values. // |headers| gets filled in from |extra_headers|. -void AppendToHeaderBlock(const char* const extra_headers[], - int extra_header_count, +void AppendToHeaderBlock(base::span<const std::string_view> extra_headers, quiche::HttpHeaderBlock* headers) { - if (!extra_header_count) + if (extra_headers.empty()) { return; + } - // Sanity check: Non-NULL header list. - DCHECK(extra_headers) << "NULL header value pair list"; + // Sanity check: Event length list. + CHECK_EQ(extra_headers.size() % 2, 0u) << "Odd length header value pair list"; // Sanity check: Non-NULL header map. - DCHECK(headers) << "NULL header map"; + CHECK(headers) << "NULL header map"; // Copy in the headers. - for (int i = 0; i < extra_header_count; i++) { - std::string_view key(extra_headers[i * 2]); - std::string_view value(extra_headers[i * 2 + 1]); - DCHECK(!key.empty()) << "Header key must not be empty."; + for (size_t i = 0; i < extra_headers.size(); i += 2) { + std::string_view key = extra_headers[i]; + std::string_view value = extra_headers[i + 1]; + CHECK(!key.empty()) << "Header key must not be empty."; headers->AppendValueOrAddHeader(key, value); } } @@ -767,8 +767,7 @@ } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGet( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id, RequestPriority request_priority, bool priority_incremental, @@ -776,23 +775,22 @@ quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "GET"; AddUrlToHeaderBlock(default_url_.spec(), &block); - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + AppendToHeaderBlock(extra_headers, &block); return ConstructSpdyHeaders(stream_id, std::move(block), request_priority, true, priority_incremental, header_request_priority); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyConnect( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id, RequestPriority priority, const HostPortPair& host_port_pair) { quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "CONNECT"; block[spdy::kHttp2AuthorityHeader] = host_port_pair.ToString(); - if (extra_headers) { - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + if (!extra_headers.empty()) { + AppendToHeaderBlock(extra_headers, &block); } else { block["user-agent"] = "test-ua"; } @@ -870,30 +868,29 @@ spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError( const char* const status, - const char* const* const extra_headers, - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id) { quiche::HttpHeaderBlock block; block[spdy::kHttp2StatusHeader] = status; block["hello"] = "bye"; - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + AppendToHeaderBlock(extra_headers, &block); spdy::SpdyHeadersIR reply(stream_id, std::move(block)); return spdy::SpdySerializedFrame(response_spdy_framer_.SerializeFrame(reply)); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyReplyError(int stream_id) { - return ConstructSpdyReplyError("500", nullptr, 0, stream_id); + return ConstructSpdyReplyError("500", base::span<const std::string_view>(), + stream_id); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyGetReply( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id) { quiche::HttpHeaderBlock block; block[spdy::kHttp2StatusHeader] = "200"; block["hello"] = "bye"; - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + AppendToHeaderBlock(extra_headers, &block); return ConstructSpdyReply(stream_id, std::move(block)); } @@ -903,33 +900,30 @@ spdy::SpdyStreamId stream_id, int64_t content_length, RequestPriority request_priority, - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, bool priority_incremental) { quiche::HttpHeaderBlock block(ConstructPostHeaderBlock(url, content_length)); - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + AppendToHeaderBlock(extra_headers, &block); return ConstructSpdyHeaders(stream_id, std::move(block), request_priority, false, priority_incremental); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructChunkedSpdyPost( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, RequestPriority request_priority, bool priority_incremental) { quiche::HttpHeaderBlock block; block[spdy::kHttp2MethodHeader] = "POST"; AddUrlToHeaderBlock(default_url_.spec(), &block); - AppendToHeaderBlock(extra_headers, extra_header_count, &block); + AppendToHeaderBlock(extra_headers, &block); return ConstructSpdyHeaders(1, std::move(block), request_priority, false, priority_incremental); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyPostReply( - const char* const extra_headers[], - int extra_header_count) { + base::span<const std::string_view> extra_headers) { // TODO(jgraettinger): Remove this method. - return ConstructSpdyGetReply(extra_headers, extra_header_count, 1); + return ConstructSpdyGetReply(extra_headers, 1); } spdy::SpdySerializedFrame SpdyTestUtil::ConstructSpdyDataFrame(int stream_id,
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index b924df9..02b5d0c 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -84,8 +84,7 @@ // where the even entries are the header names, and the odd entries are the // header values. // |headers| gets filled in from |extra_headers|. -void AppendToHeaderBlock(const char* const extra_headers[], - int extra_header_count, +void AppendToHeaderBlock(base::span<const std::string_view> extra_headers, quiche::HttpHeaderBlock* headers); // Create an async MockWrite from the given spdy::SpdySerializedFrame. @@ -358,8 +357,7 @@ // will vary the most between calls. If |direct| is false, the // the full url will be used instead of simply the path. spdy::SpdySerializedFrame ConstructSpdyGet( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id, RequestPriority request_priority, bool priority_incremental = kDefaultPriorityIncremental, @@ -369,8 +367,7 @@ // is nullptr, it includes just "user-agent" "test-ua" as that is commonly // required. spdy::SpdySerializedFrame ConstructSpdyConnect( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id, RequestPriority priority, const HostPortPair& host_port_pair); @@ -406,8 +403,7 @@ // |extra_headers| are the extra header-value pairs, which typically // will vary the most between calls. spdy::SpdySerializedFrame ConstructSpdyGetReply( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id); // Constructs a standard SPDY HEADERS frame with an Internal Server @@ -417,8 +413,7 @@ // Constructs a standard SPDY HEADERS frame with the specified status code. spdy::SpdySerializedFrame ConstructSpdyReplyError( const char* const status, - const char* const* const extra_headers, - int extra_header_count, + base::span<const std::string_view> extra_headers, int stream_id); // Constructs a standard SPDY POST HEADERS frame. @@ -429,16 +424,14 @@ spdy::SpdyStreamId stream_id, int64_t content_length, RequestPriority request_priority, - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, bool priority_incremental = kDefaultPriorityIncremental); // Constructs a chunked transfer SPDY POST HEADERS frame. // |extra_headers| are the extra header-value pairs, which typically // will vary the most between calls. spdy::SpdySerializedFrame ConstructChunkedSpdyPost( - const char* const extra_headers[], - int extra_header_count, + base::span<const std::string_view> extra_headers, RequestPriority request_priority = RequestPriority::DEFAULT_PRIORITY, bool priority_incremental = kDefaultPriorityIncremental); @@ -446,8 +439,7 @@ // |extra_headers| are the extra header-value pairs, which typically // will vary the most between calls. spdy::SpdySerializedFrame ConstructSpdyPostReply( - const char* const extra_headers[], - int extra_header_count); + base::span<const std::string_view> extra_headers); // Constructs a single SPDY data frame with the contents "hello!" spdy::SpdySerializedFrame ConstructSpdyDataFrame(int stream_id, bool fin);
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc index 64e03dd0..8d03d9a7 100644 --- a/net/websockets/websocket_stream_test.cc +++ b/net/websockets/websocket_stream_test.cc
@@ -242,12 +242,11 @@ // First request. This is necessary, because a WebSockets request currently // does not open a new HTTP/2 connection, it only uses an existing one. - const char* const kExtraRequestHeaders[] = { + std::string_view kExtraRequestHeaders[] = { "user-agent", "", "accept-encoding", "gzip, deflate", "accept-language", "en-us,fr"}; - frames_.push_back(spdy_util_.ConstructSpdyGet( - kExtraRequestHeaders, std::size(kExtraRequestHeaders) / 2, 1, - DEFAULT_PRIORITY)); + frames_.push_back( + spdy_util_.ConstructSpdyGet(kExtraRequestHeaders, 1, DEFAULT_PRIORITY)); AddWrite(&frames_.back()); // SETTINGS ACK frame sent by the server in response to the client's @@ -256,7 +255,8 @@ AddRead(&frames_.back()); // Response headers to first request. - frames_.push_back(spdy_util_.ConstructSpdyGetReply(nullptr, 0, 1)); + frames_.push_back(spdy_util_.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); AddRead(&frames_.back()); // Response body to first request. @@ -280,20 +280,19 @@ } else { // Response to WebSocket request. std::vector<std::string> extra_response_header_keys; - std::vector<const char*> extra_response_headers_vector; + std::vector<std::string_view> extra_response_headers_vector; for (const auto& extra_header : extra_response_headers) { // Save a lowercase copy of the header key. extra_response_header_keys.push_back( base::ToLowerASCII(extra_header.first)); // Save a pointer to this lowercase copy. extra_response_headers_vector.push_back( - extra_response_header_keys.back().c_str()); + extra_response_header_keys.back()); // Save a pointer to the original header value provided by the caller. - extra_response_headers_vector.push_back(extra_header.second.c_str()); + extra_response_headers_vector.push_back(extra_header.second); } frames_.push_back(spdy_util_.ConstructSpdyReplyError( - http2_response_status_, extra_response_headers_vector.data(), - extra_response_headers_vector.size() / 2, 3)); + http2_response_status_, extra_response_headers_vector, 3)); AddRead(&frames_.back()); // WebSocket data received.
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 298b0e90..b19bfa46 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -2111,8 +2111,9 @@ : url_request_context_->cert_verifier(); cert_verifier->Verify2QwacBinding( binding, hostname, tls_certificate, std::move(callback), - net::NetLogWithSource::Make(url_request_context_->net_log(), - net::NetLogSourceType::CERT_VERIFIER_JOB)); + net::NetLogWithSource::Make( + url_request_context_->net_log(), + net::NetLogSourceType::CERT_VERIFIER_2QWAC_JOB)); } void NetworkContext::NotifyExternalCacheHit(const GURL& url,
diff --git a/services/network/proxy_resolving_client_socket_unittest.cc b/services/network/proxy_resolving_client_socket_unittest.cc index c893465..164b446b 100644 --- a/services/network/proxy_resolving_client_socket_unittest.cc +++ b/services/network/proxy_resolving_client_socket_unittest.cc
@@ -195,15 +195,17 @@ // a different session. net::SpdyTestUtil spdy_util1; spdy::SpdySerializedFrame connect_dest1(spdy_util1.ConstructSpdyConnect( - nullptr, 0, 1, net::HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + net::HttpProxyConnectJob::kH2QuicTunnelPriority, net::HostPortPair::FromURL(kDestination1))); - spdy::SpdySerializedFrame connect_dest1_resp( - spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_dest1_resp(spdy_util1.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); spdy::SpdySerializedFrame connect_dest3(spdy_util1.ConstructSpdyConnect( - nullptr, 0, 3, net::HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 3, + net::HttpProxyConnectJob::kH2QuicTunnelPriority, net::HostPortPair::FromURL(kDestination3))); - spdy::SpdySerializedFrame connect_dest3_resp( - spdy_util1.ConstructSpdyGetReply(nullptr, 0, 3)); + spdy::SpdySerializedFrame connect_dest3_resp(spdy_util1.ConstructSpdyGetReply( + base::span<const std::string_view>(), 3)); net::MockWrite spdy_writes[] = { net::CreateMockWrite(connect_dest1, 0), @@ -224,10 +226,11 @@ net::SpdyTestUtil spdy_util2; spdy::SpdySerializedFrame connect_dest2(spdy_util2.ConstructSpdyConnect( - nullptr, 0, 1, net::HttpProxyConnectJob::kH2QuicTunnelPriority, + base::span<const std::string_view>(), 1, + net::HttpProxyConnectJob::kH2QuicTunnelPriority, net::HostPortPair::FromURL(kDestination2))); - spdy::SpdySerializedFrame connect_dest2_resp( - spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1)); + spdy::SpdySerializedFrame connect_dest2_resp(spdy_util2.ConstructSpdyGetReply( + base::span<const std::string_view>(), 1)); net::MockWrite spdy_writes2[] = { net::CreateMockWrite(connect_dest2, 0),
diff --git a/testing/buildbot/filters/pixel_tests.filter b/testing/buildbot/filters/pixel_tests.filter index 524ccab..49e6b42b 100644 --- a/testing/buildbot/filters/pixel_tests.filter +++ b/testing/buildbot/filters/pixel_tests.filter
@@ -95,6 +95,7 @@ *PasswordBubbleBrowserTest.* *PasswordAutomaticSaveBubbleBrowserTest.* *PasswordCrossDomainConfirmationPopupViewBrowsertest.* +*PasswordChangeToastBrowserTest.InvokeUi_* *PasswordChangeUiBrowserTest.* *PasswordGenerationPopupViewBrowsertest.* *PasswordGenerationPopupViewWithSoftNudgeBrowsertest.*
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7846ceae..2d9408f4 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -761,6 +761,21 @@ ] } ], + "AndroidProgressBarVisualUpdate": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AndroidProgressBarVisualUpdate" + ] + } + ] + } + ], "AndroidRaiseDisplayCriticalThreadPriority": [ { "platforms": [ @@ -9293,6 +9308,24 @@ ] } ], + "EnableWatermarkCustomization": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "EnableWatermarkCustomization" + ] + } + ] + } + ], "EncryptedPrefHashing": [ { "platforms": [ @@ -11618,6 +11651,27 @@ ] } ], + "HeapProfilerMultiKeyHashSet": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "HeapProfilerMultiKeyHashSet" + ] + } + ] + } + ], "HeapProfilingLoadFactor": [ { "platforms": [ @@ -13959,6 +14013,24 @@ ] } ], + "LensOverlayBackToLivePage": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "LensOverlayBackToLivePageEnabled", + "enable_features": [ + "LensOverlayBackToPage" + ] + } + ] + } + ], "LensSearchSidePanelDefaultWidth": [ { "platforms": [ @@ -14326,24 +14398,6 @@ ] } ], - "LoginDbDeprecationAndroid": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "login-db-deprecation-export-delay-seconds": "5" - }, - "enable_features": [ - "LoginDbDeprecationAndroid" - ] - } - ] - } - ], "LongAnimationFrameSourceCharPosition": [ { "platforms": [ @@ -16114,6 +16168,21 @@ ] } ], + "OmniboxMobileParityUpdateV2": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "OmniboxMobileParityUpdateV2" + ] + } + ] + } + ], "OmniboxOnDeviceBrainModel": [ { "platforms": [ @@ -20064,6 +20133,7 @@ { "name": "Enabled", "enable_features": [ + "AvoidCloneArgsOnExtensionFunctionDispatch", "AvoidUnnecessaryGetMinimizeButtonOffset", "ReducePPMs" ] @@ -25078,23 +25148,6 @@ ] } ], - "UnoPhase2FastFollowsAndroid": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "UnoForAuto", - "UnoPhase2FollowUp", - "UseHostedDomainForManagementCheckOnSignin" - ] - } - ] - } - ], "UploadOfficeToCloud": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index b89c600..cb43254 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit b89c600819486f7187ac958b6396eafa2b1bd1ac +Subproject commit cb432540e120916a9f503be74d128be74ec2ae8e
diff --git a/third_party/blink/common/messaging/transferable_message_mojom_traits.cc b/third_party/blink/common/messaging/transferable_message_mojom_traits.cc index eebdd19..e07651f 100644 --- a/third_party/blink/common/messaging/transferable_message_mojom_traits.cc +++ b/third_party/blink/common/messaging/transferable_message_mojom_traits.cc
@@ -21,7 +21,7 @@ !data.ReadImageBitmapContentsArray(&out->image_bitmap_contents_array) || !data.ReadPorts(&ports) || !data.ReadStreamChannels(&stream_channels) || !data.ReadUserActivation(&out->user_activation) || - !data.ReadParentTaskId(&out->parent_task_id)) { + !data.ReadTaskStateId(&out->task_state_id)) { return false; }
diff --git a/third_party/blink/common/security/address_space_feature.cc b/third_party/blink/common/security/address_space_feature.cc index b896311..4369909 100644 --- a/third_party/blink/common/security/address_space_feature.cc +++ b/third_party/blink/common/security/address_space_feature.cc
@@ -77,53 +77,53 @@ constexpr struct FeatureEntry kFeatureMap[] = { { {AddressSpace::kPrivate, kNonSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateNonSecureContextEmbeddedLocal, - Feature::kAddressSpacePrivateNonSecureContextNavigatedToLocal, + Feature::kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpaceLocalNonSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kPrivate, kSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateSecureContextEmbeddedLocal, - Feature::kAddressSpacePrivateSecureContextNavigatedToLocal, + Feature::kAddressSpaceLocalSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpaceLocalSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kPublic, kNonSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpacePublicNonSecureContextEmbeddedLocal, - Feature::kAddressSpacePublicNonSecureContextNavigatedToLocal, + Feature::kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpacePublicNonSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kPublic, kSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpacePublicSecureContextEmbeddedLocal, - Feature::kAddressSpacePublicSecureContextNavigatedToLocal, + Feature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpacePublicSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kPublic, kNonSecureContext, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicNonSecureContextEmbeddedPrivate, - Feature::kAddressSpacePublicNonSecureContextNavigatedToPrivate, + Feature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, + Feature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, }, { {AddressSpace::kPublic, kSecureContext, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicSecureContextEmbeddedPrivate, - Feature::kAddressSpacePublicSecureContextNavigatedToPrivate, + Feature::kAddressSpacePublicSecureContextEmbeddedLocalV2, + Feature::kAddressSpacePublicSecureContextNavigatedToLocalV2, }, { {AddressSpace::kUnknown, kNonSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLocal, - Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLocal, + Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kUnknown, kSecureContext, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownSecureContextEmbeddedLocal, - Feature::kAddressSpaceUnknownSecureContextNavigatedToLocal, + Feature::kAddressSpaceUnknownSecureContextEmbeddedLoopbackV2, + Feature::kAddressSpaceUnknownSecureContextNavigatedToLoopbackV2, }, { {AddressSpace::kUnknown, kNonSecureContext, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownNonSecureContextEmbeddedPrivate, - Feature::kAddressSpaceUnknownNonSecureContextNavigatedToPrivate, + Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLocalV2, + Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLocalV2, }, { {AddressSpace::kUnknown, kSecureContext, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownSecureContextEmbeddedPrivate, - Feature::kAddressSpaceUnknownSecureContextNavigatedToPrivate, + Feature::kAddressSpaceUnknownSecureContextEmbeddedLocalV2, + Feature::kAddressSpaceUnknownSecureContextNavigatedToLocalV2, }, };
diff --git a/third_party/blink/common/security/address_space_feature_unittest.cc b/third_party/blink/common/security/address_space_feature_unittest.cc index a2b0513f..717f2a8 100644 --- a/third_party/blink/common/security/address_space_feature_unittest.cc +++ b/third_party/blink/common/security/address_space_feature_unittest.cc
@@ -132,102 +132,102 @@ { {FetchType::kSubresource, AddressSpace::kUnknown, false, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownNonSecureContextEmbeddedPrivate, + Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLocalV2, }, { {FetchType::kSubresource, AddressSpace::kUnknown, true, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownSecureContextEmbeddedPrivate, + Feature::kAddressSpaceUnknownSecureContextEmbeddedLocalV2, }, { {FetchType::kSubresource, AddressSpace::kUnknown, false, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLocal, + Feature::kAddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2, }, { {FetchType::kSubresource, AddressSpace::kUnknown, true, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownSecureContextEmbeddedLocal, + Feature::kAddressSpaceUnknownSecureContextEmbeddedLoopbackV2, }, { {FetchType::kSubresource, AddressSpace::kPublic, false, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicNonSecureContextEmbeddedPrivate, + Feature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, }, { {FetchType::kSubresource, AddressSpace::kPublic, true, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicSecureContextEmbeddedPrivate, + Feature::kAddressSpacePublicSecureContextEmbeddedLocalV2, }, { {FetchType::kSubresource, AddressSpace::kPublic, false, AddressSpace::kLocal}, - Feature::kAddressSpacePublicNonSecureContextEmbeddedLocal, + Feature::kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2, }, { {FetchType::kSubresource, AddressSpace::kPublic, true, AddressSpace::kLocal}, - Feature::kAddressSpacePublicSecureContextEmbeddedLocal, + Feature::kAddressSpacePublicSecureContextEmbeddedLoopbackV2, }, { {FetchType::kSubresource, AddressSpace::kPrivate, false, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateNonSecureContextEmbeddedLocal, + Feature::kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2, }, { {FetchType::kSubresource, AddressSpace::kPrivate, true, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateSecureContextEmbeddedLocal, + Feature::kAddressSpaceLocalSecureContextEmbeddedLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kUnknown, false, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownNonSecureContextNavigatedToPrivate, + Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLocalV2, }, { {FetchType::kNavigation, AddressSpace::kUnknown, true, AddressSpace::kPrivate}, - Feature::kAddressSpaceUnknownSecureContextNavigatedToPrivate, + Feature::kAddressSpaceUnknownSecureContextNavigatedToLocalV2, }, { {FetchType::kNavigation, AddressSpace::kUnknown, false, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLocal, + Feature::kAddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kUnknown, true, AddressSpace::kLocal}, - Feature::kAddressSpaceUnknownSecureContextNavigatedToLocal, + Feature::kAddressSpaceUnknownSecureContextNavigatedToLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kPublic, false, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicNonSecureContextNavigatedToPrivate, + Feature::kAddressSpacePublicNonSecureContextNavigatedToLocalV2, }, { {FetchType::kNavigation, AddressSpace::kPublic, true, AddressSpace::kPrivate}, - Feature::kAddressSpacePublicSecureContextNavigatedToPrivate, + Feature::kAddressSpacePublicSecureContextNavigatedToLocalV2, }, { {FetchType::kNavigation, AddressSpace::kPublic, false, AddressSpace::kLocal}, - Feature::kAddressSpacePublicNonSecureContextNavigatedToLocal, + Feature::kAddressSpacePublicNonSecureContextNavigatedToLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kPublic, true, AddressSpace::kLocal}, - Feature::kAddressSpacePublicSecureContextNavigatedToLocal, + Feature::kAddressSpacePublicSecureContextNavigatedToLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kPrivate, false, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateNonSecureContextNavigatedToLocal, + Feature::kAddressSpaceLocalNonSecureContextNavigatedToLoopbackV2, }, { {FetchType::kNavigation, AddressSpace::kPrivate, true, AddressSpace::kLocal}, - Feature::kAddressSpacePrivateSecureContextNavigatedToLocal, + Feature::kAddressSpaceLocalSecureContextNavigatedToLoopbackV2, }, };
diff --git a/third_party/blink/public/common/messaging/transferable_message.h b/third_party/blink/public/common/messaging/transferable_message.h index bf325a4..6678039 100644 --- a/third_party/blink/public/common/messaging/transferable_message.h +++ b/third_party/blink/public/common/messaging/transferable_message.h
@@ -47,8 +47,8 @@ mojom::DelegatedCapability delegated_capability = mojom::DelegatedCapability::kNone; - // The transferable message's parent task ID. - std::optional<scheduler::TaskAttributionId> parent_task_id; + // The transferable message's task state ID. + std::optional<scheduler::TaskAttributionId> task_state_id; }; } // namespace blink
diff --git a/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h b/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h index 63cbe87a..dc87261 100644 --- a/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h +++ b/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h
@@ -55,11 +55,11 @@ return input.delegated_capability; } - static std::optional<blink::scheduler::TaskAttributionId> parent_task_id( + static std::optional<blink::scheduler::TaskAttributionId> task_state_id( blink::TransferableMessage& input) { - return input.parent_task_id + return input.task_state_id ? std::make_optional(blink::scheduler::TaskAttributionId( - input.parent_task_id.value())) + input.task_state_id.value())) : std::nullopt; }
diff --git a/third_party/blink/public/mojom/messaging/transferable_message.mojom b/third_party/blink/public/mojom/messaging/transferable_message.mojom index 92948ee..4a45d2d 100644 --- a/third_party/blink/public/mojom/messaging/transferable_message.mojom +++ b/third_party/blink/public/mojom/messaging/transferable_message.mojom
@@ -37,6 +37,6 @@ UserActivationSnapshot? user_activation; // What capability, if any, is delegated to the destination frame. DelegatedCapability delegated_capability = kNone; - // The ID of the task initiating the message. - TaskAttributionId? parent_task_id; + // The TaskAttributionId of the task initiating the message, if any. + TaskAttributionId? task_state_id; };
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index d0bfe78..a70aeca 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3009,26 +3009,26 @@ kPaymentHandlerStandardizedPaymentMethodIdentifier = 3750, kWebCodecsAudioEncoder = 3751, kEmbeddedCrossOriginFrameWithoutFrameAncestorsOrXFO = 3752, - kAddressSpacePrivateSecureContextEmbeddedLocal = 3753, - kAddressSpacePrivateNonSecureContextEmbeddedLocal = 3754, - kAddressSpacePublicSecureContextEmbeddedLocal = 3755, - kAddressSpacePublicNonSecureContextEmbeddedLocal = 3756, - kAddressSpacePublicSecureContextEmbeddedPrivate = 3757, - kAddressSpacePublicNonSecureContextEmbeddedPrivate = 3758, - kAddressSpaceUnknownSecureContextEmbeddedLocal = 3759, - kAddressSpaceUnknownNonSecureContextEmbeddedLocal = 3760, - kAddressSpaceUnknownSecureContextEmbeddedPrivate = 3761, - kAddressSpaceUnknownNonSecureContextEmbeddedPrivate = 3762, - kAddressSpacePrivateSecureContextNavigatedToLocal = 3763, - kAddressSpacePrivateNonSecureContextNavigatedToLocal = 3764, - kAddressSpacePublicSecureContextNavigatedToLocal = 3765, - kAddressSpacePublicNonSecureContextNavigatedToLocal = 3766, - kAddressSpacePublicSecureContextNavigatedToPrivate = 3767, - kAddressSpacePublicNonSecureContextNavigatedToPrivate = 3768, - kAddressSpaceUnknownSecureContextNavigatedToLocal = 3769, - kAddressSpaceUnknownNonSecureContextNavigatedToLocal = 3770, - kAddressSpaceUnknownSecureContextNavigatedToPrivate = 3771, - kAddressSpaceUnknownNonSecureContextNavigatedToPrivate = 3772, + kAddressSpaceLocalSecureContextEmbeddedLoopbackV2 = 3753, + kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2 = 3754, + kAddressSpacePublicSecureContextEmbeddedLoopbackV2 = 3755, + kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2 = 3756, + kAddressSpacePublicSecureContextEmbeddedLocalV2 = 3757, + kAddressSpacePublicNonSecureContextEmbeddedLocalV2 = 3758, + kAddressSpaceUnknownSecureContextEmbeddedLoopbackV2 = 3759, + kAddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2 = 3760, + kAddressSpaceUnknownSecureContextEmbeddedLocalV2 = 3761, + kAddressSpaceUnknownNonSecureContextEmbeddedLocalV2 = 3762, + kAddressSpaceLocalSecureContextNavigatedToLoopbackV2 = 3763, + kAddressSpaceLocalNonSecureContextNavigatedToLoopbackV2 = 3764, + kAddressSpacePublicSecureContextNavigatedToLoopbackV2 = 3765, + kAddressSpacePublicNonSecureContextNavigatedToLoopbackV2 = 3766, + kAddressSpacePublicSecureContextNavigatedToLocalV2 = 3767, + kAddressSpacePublicNonSecureContextNavigatedToLocalV2 = 3768, + kAddressSpaceUnknownSecureContextNavigatedToLoopbackV2 = 3769, + kAddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2 = 3770, + kAddressSpaceUnknownSecureContextNavigatedToLocalV2 = 3771, + kAddressSpaceUnknownNonSecureContextNavigatedToLocalV2 = 3772, kOBSOLETE_RTCPeerConnectionSdpSemanticsPlanB = 3773, // The items above roughly this point are available in the M89 branch. kFetchRespondWithNoResponseWithUsedRequestBody = 3774, @@ -4902,6 +4902,7 @@ kV8URLPattern_Generate_Method = 5593, kSelectMultipleSizeOne = 5594, kWebGPUFeatureLevelCompatibility = 5595, + kOverscrollBehaviorOnNonScrollableScrollContainer = 5596, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots. Also don't add extra
diff --git a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc index 46b87cb..e1b6c4e 100644 --- a/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc +++ b/third_party/blink/renderer/bindings/core/v8/callback_invoke_helper.cc
@@ -104,7 +104,7 @@ if constexpr (std::is_same< CallbackBase, CallbackFunctionWithTaskAttributionBase>::value) { - task_state_to_propagate = callback_->GetParentTask(); + task_state_to_propagate = callback_->GetTaskState(); } task_attribution_scope_ = tracker->MaybeCreateTaskScopeForCallback( callback_->CallbackRelevantScriptState(), task_state_to_propagate);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 0dbab39..0aba76d3 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1403,10 +1403,14 @@ IncrementResolvedStyleCounters(style_request, GetDocument()); if (InvalidationTracingFlag::IsEnabled()) [[unlikely]] { + Element* styled_element = state.GetStyledElement(); + if (styled_element == nullptr) { + styled_element = element; + } DEVTOOLS_TIMELINE_TRACE_EVENT_INSTANT_WITH_CATEGORIES( TRACE_DISABLED_BY_DEFAULT("devtools.timeline.invalidationTracking"), "StyleResolver::ResolveStyle", - inspector_style_resolver_resolve_style_event::Data, element, + inspector_style_resolver_resolve_style_event::Data, styled_element, style_request.pseudo_id); }
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc index 63eb764..2fa3045 100644 --- a/third_party/blink/renderer/core/dom/container_node.cc +++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -383,11 +383,11 @@ const NodeVector& post_insertion_notification_targets) { Node* unchanged_previous = targets.size() > 0 ? targets[0]->previousSibling() : nullptr; - const Document& document = GetDocument(); for (const auto& target_node : targets) { ChildrenChanged(ChildrenChange::ForInsertion( *target_node, unchanged_previous, next, ChildrenChangeSource::kAPI)); - CheckSoftNavigationHeuristicsTracking(document, *target_node); + SoftNavigationHeuristics::InsertedNode(target_node, + /*container_node=*/this); } for (const auto& descendant : post_insertion_notification_targets) { if (descendant->isConnected()) @@ -1871,31 +1871,6 @@ AppendChildren(nodes, exception_state); } -void ContainerNode::CheckSoftNavigationHeuristicsTracking( - const Document& document, - Node& inserted_node) { - if (!document.IsTrackingSoftNavigationHeuristics()) { - return; - } - if (!inserted_node.isConnected()) { - return; - } - LocalDOMWindow* window = document.domWindow(); - if (!window) { - return; - } - if (SoftNavigationHeuristics* heuristics = - window->GetSoftNavigationHeuristics()) { - // When a child node, which is an HTML-element, is modified within a parent - // (added, moved, etc), mark that child as modified by soft navigation. - // Otherwise, if the child is not an HTML-element, mark the parent instead. - // TODO(crbug.com/1521100): This does not filter out updates from isolated - // worlds. Should it? - Node* updated_node = inserted_node.IsHTMLElement() ? &inserted_node : this; - heuristics->ModifiedDOM(updated_node); - } -} - String ContainerNode::getHTML(const GetHTMLOptions* options, ExceptionState& exception_state) const { DCHECK(options && options->hasSerializableShadowRoots())
diff --git a/third_party/blink/renderer/core/dom/container_node.h b/third_party/blink/renderer/core/dom/container_node.h index f83857b1..b445fcaa 100644 --- a/third_party/blink/renderer/core/dom/container_node.h +++ b/third_party/blink/renderer/core/dom/container_node.h
@@ -572,9 +572,6 @@ inline bool IsHostIncludingInclusiveAncestorOfThis(const Node&, ExceptionState&) const; - void CheckSoftNavigationHeuristicsTracking(const Document& document, - Node& inserted_node); - Member<Node> first_child_; Member<Node> last_child_; };
diff --git a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5 b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5 index 2a04e37..5a7fb65 100644 --- a/third_party/blink/renderer/core/frame/deprecation/deprecation.json5 +++ b/third_party/blink/renderer/core/frame/deprecation/deprecation.json5
@@ -268,9 +268,9 @@ message: "The website requested a subresource from a network that it could only access because of its users' privileged network position. These requests expose non-public devices and servers to the internet, increasing the risk of a cross-site request forgery (CSRF) attack, and/or information leakage. To mitigate these risks, Chrome deprecates requests to non-public subresources when initiated from non-secure contexts, and will start blocking them.", translation_note: "This warning occurs when an insecure context (e.g., HTTP) requests a private resource (not on open internet). This is done to mitigate the potential for CSRF and other attacks.", web_features: [ - "kAddressSpacePrivateNonSecureContextEmbeddedLocal", - "kAddressSpacePublicNonSecureContextEmbeddedLocal", - "kAddressSpacePublicNonSecureContextEmbeddedPrivate", + "kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2", + "kAddressSpacePublicNonSecureContextEmbeddedLocalV2", + "kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2", ], chrome_status_feature: 5436853517811712, milestone: 92,
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index 8a10582..47d4a45 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -187,7 +187,7 @@ auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker && script_state->World().IsMainWorld()) { - callback->SetParentTask(tracker->RunningTask()); + callback->SetTaskState(tracker->CurrentTaskState()); } } @@ -993,17 +993,17 @@ void LocalDOMWindow::DispatchPopstateEvent( scoped_refptr<SerializedScriptValue> state_object, - scheduler::TaskAttributionInfo* parent_task, + scheduler::TaskAttributionInfo* task_state, bool has_ua_visual_transition) { DCHECK(GetFrame()); std::optional<scheduler::TaskAttributionTracker::TaskScope> task_attribution_scope; - if (parent_task) { + if (task_state) { auto* tracker = scheduler::TaskAttributionTracker::From(GetIsolate()); ScriptState* script_state = ToScriptStateForMainWorld(GetFrame()); if (script_state && tracker) { task_attribution_scope = tracker->CreateTaskScope( - script_state, parent_task, + script_state, task_state, scheduler::TaskAttributionTracker::TaskScopeType::kPopState); } } @@ -1242,7 +1242,7 @@ scheduler::TaskAttributionInfo* task_context = nullptr; if (source == this) { if (auto* tracker = scheduler::TaskAttributionTracker::From(GetIsolate())) { - task_context = tracker->RunningTask(); + task_context = tracker->CurrentTaskState(); } } @@ -1275,7 +1275,7 @@ scoped_refptr<const SecurityOrigin> intended_target_origin, SourceLocation* location, const base::UnguessableToken& source_agent_cluster_id, - scheduler::TaskAttributionInfo* parent_task) { + scheduler::TaskAttributionInfo* task_state) { // Do not report postMessage tasks to the ad tracker. This allows non-ad // script to perform operations in response to events created by ad frames. probe::AsyncTask async_task(this, event->async_task_context(), @@ -1296,12 +1296,12 @@ std::optional<scheduler::TaskAttributionTracker::TaskScope> task_attribution_scope; - if (parent_task) { + if (task_state) { if (ScriptState* script_state = ToScriptStateForMainWorld(GetFrame())) { auto* tracker = scheduler::TaskAttributionTracker::From(GetIsolate()); CHECK(tracker); task_attribution_scope = tracker->CreateTaskScope( - script_state, parent_task, + script_state, task_state, scheduler::TaskAttributionTracker::TaskScopeType::kPostMessage); } }
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h index a517b2df..28640c3a 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.h +++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -406,7 +406,7 @@ scoped_refptr<const SecurityOrigin> intended_target_origin, SourceLocation* location, const base::UnguessableToken& source_agent_cluster_id, - scheduler::TaskAttributionInfo* parent_task); + scheduler::TaskAttributionInfo* task_state); void DispatchMessageEventWithOriginCheck( const SecurityOrigin* intended_target_origin, @@ -432,7 +432,7 @@ void EnqueueNonPersistedPageshowEvent(); void EnqueueHashchangeEvent(const String& old_url, const String& new_url); void DispatchPopstateEvent(scoped_refptr<SerializedScriptValue>, - scheduler::TaskAttributionInfo* parent_task, + scheduler::TaskAttributionInfo* task_state, bool has_ua_visual_transition); void DispatchWindowLoadEvent(); void DocumentWasClosed();
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index b68b7396..046c3c4 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -67,6 +67,7 @@ #include "third_party/blink/renderer/core/navigation_api/navigation_api.h" #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" +#include "third_party/blink/renderer/core/scroll/scroll_into_view_util.h" #include "third_party/blink/renderer/core/speculation_rules/document_speculation_rules.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" @@ -854,14 +855,15 @@ PaintLayerScrollableArea* HTMLAnchorElement::AncestorScrollableAreaOfScrollTargetElement() const { Element* scroll_target = ScrollTargetElement(); - if (!scroll_target) { + if (!scroll_target || !scroll_target->GetLayoutBox()) { return nullptr; } - for (Element* parent = - LayoutTreeBuilderTraversal::ParentElement(*scroll_target); - parent; parent = LayoutTreeBuilderTraversal::ParentElement(*parent)) { - if (parent->GetLayoutBox() && parent->GetLayoutBox()->GetScrollableArea()) { - return parent->GetLayoutBox()->GetScrollableArea(); + for (LayoutBox* parent_box = scroll_target->GetLayoutBox()->ParentBox(); + parent_box; parent_box = parent_box->ParentBox()) { + if (ScrollableArea* scrollable_area = + scroll_into_view_util::GetScrollableAreaForLayoutBox( + *parent_box, /*make_visible_in_visual_viewport=*/false)) { + return DynamicTo<PaintLayerScrollableArea>(scrollable_area); } } return nullptr;
diff --git a/third_party/blink/renderer/core/inspector/invalidation_set_to_selector_map_test.cc b/third_party/blink/renderer/core/inspector/invalidation_set_to_selector_map_test.cc index 63f3404..74e56b90 100644 --- a/third_party/blink/renderer/core/inspector/invalidation_set_to_selector_map_test.cc +++ b/third_party/blink/renderer/core/inspector/invalidation_set_to_selector_map_test.cc
@@ -1006,6 +1006,64 @@ EXPECT_EQ(SelectorAtIndex(selector_list, 0), ".a *"); } +TEST_F(InvalidationSetToSelectorMapTest, + AttributeDescendantsOnSubtreeInvalidationForSvgUse) { + SetBodyInnerHTML(R"HTML( + <style> + .a * { fill: green; } + </style> + <body> + <div id="parent"> + <svg width="100" height="100"> + <use href="#myCircle"/> + </svg> + </div> + <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"> + <defs> + <circle id="myCircle" cx="50" cy="50" r="40" /> + </defs> + </svg> + </body> + )HTML"); + + StartTracing(); + + GetElementById("parent")->setAttribute(html_names::kClassAttr, + AtomicString("a")); + UpdateAllLifecyclePhasesForTest(); + auto analyzer = StopTracing(); + + // Validate that we can follow ResolveStyle events to the invalidation root. + trace_analyzer::TraceEventVector resolve_events; + analyzer->FindEvents( + trace_analyzer::Query::EventNameIs("StyleResolver::ResolveStyle"), + &resolve_events); + ASSERT_EQ(resolve_events.size(), 4u); + int div_id = CheckResolveStyleEvent(resolve_events[0], std::nullopt, + std::nullopt, kPseudoIdNone); + int svg_id = CheckResolveStyleEvent(resolve_events[1], std::nullopt, div_id, + kPseudoIdNone); + int use_id = CheckResolveStyleEvent(resolve_events[2], std::nullopt, svg_id, + kPseudoIdNone); + CheckResolveStyleEvent(resolve_events[3], std::nullopt, use_id, + kPseudoIdNone); + + // Validate we can follow the invalidation root to an invalidation event. + trace_analyzer::TraceEventVector invalidation_events; + analyzer->FindEvents(trace_analyzer::Query::EventNameIs( + "StyleInvalidatorInvalidationTracking"), + &invalidation_events); + ASSERT_EQ(invalidation_events.size(), 1u); + base::Value::Dict data_dict = + invalidation_events[0]->GetKnownArgAsDict("data"); + std::optional<int> node_id = data_dict.FindInt("nodeId"); + EXPECT_EQ(node_id.value_or(-1), div_id); + base::Value::List* selector_list = data_dict.FindList("selectors"); + ASSERT_NE(selector_list, nullptr); + EXPECT_EQ(selector_list->size(), 1u); + EXPECT_EQ(SelectorAtIndex(selector_list, 0), ".a *"); +} + TEST_F(InvalidationSetToSelectorMapTest, AttributePseudos) { SetBodyInnerHTML(R"HTML( <style> @@ -1035,7 +1093,7 @@ std::nullopt, kPseudoIdNone); int base_node_id = CheckResolveStyleEvent(resolve_events[1], std::nullopt, parent_node_id, kPseudoIdNone); - CheckResolveStyleEvent(resolve_events[2], base_node_id, parent_node_id, + CheckResolveStyleEvent(resolve_events[2], std::nullopt, base_node_id, kPseudoIdFirstLetter); // Validate we can follow the invalidation root to an invalidation event.
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc index e33f8ad..ef97410 100644 --- a/third_party/blink/renderer/core/layout/hit_test_result.cc +++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -300,7 +300,8 @@ while (cur_box) { if (cur_box->IsGlobalRootScroller() || (cur_box->IsScrollContainer() && - cur_box->GetScrollableArea()->ScrollsOverflow())) { + (cur_box->GetScrollableArea()->ScrollsOverflow() || + !cur_box->GetScrollableArea()->CanPropagateScroll()))) { return cur_box->GetScrollableArea()->GetScrollElementId(); }
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index e4175272..7a3ede9 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1164,7 +1164,7 @@ soft_navigation_heuristics_task_id ? tracker->CommitSameDocumentNavigation( soft_navigation_heuristics_task_id.value()) - : tracker->RunningTask(); + : tracker->CurrentTaskState(); } }
diff --git a/third_party/blink/renderer/core/loader/image_loader.cc b/third_party/blink/renderer/core/loader/image_loader.cc index 965b33b1..5433528 100644 --- a/third_party/blink/renderer/core/loader/image_loader.cc +++ b/third_party/blink/renderer/core/loader/image_loader.cc
@@ -64,6 +64,7 @@ #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/svg/graphics/svg_image.h" #include "third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h" +#include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" @@ -667,6 +668,13 @@ delay_until_do_update_from_element_ = nullptr; } + // Soft Navigation tracking needs to know about image changes caused by + // attribute changes, e.g. changing an HTMLImageElement's src, so it can + // attribute the subsequent paint. + if (update_behavior == kUpdateIgnorePreviousError) { + SoftNavigationHeuristics::ModifiedNode(element_.Get()); + } + const KURL image_source_kurl = ImageSourceToKURL(image_source_url); if (ShouldLoadImmediately(image_source_kurl) && update_behavior != kUpdateFromMicrotask) {
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index c67791e7..fa8c51a7 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -49,9 +49,9 @@ // The list of features which should be reported as deprecated. constexpr WebFeature kDeprecatedAddressSpaceFeatures[] = { - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedPrivate, - WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocal, - WebFeature::kAddressSpacePrivateNonSecureContextEmbeddedLocal, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLocalV2, + WebFeature::kAddressSpacePublicNonSecureContextEmbeddedLoopbackV2, + WebFeature::kAddressSpaceLocalNonSecureContextEmbeddedLoopbackV2, }; // Returns whether |feature| is deprecated.
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc index fd9baa2..f51e7ee 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -56,7 +56,7 @@ } result.delegated_capability = message.delegated_capability; - result.parent_task_id = message.parent_task_id; + result.task_state_id = message.task_state_id; if (!message.array_buffer_contents_array.empty()) { SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array;
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.h b/third_party/blink/renderer/core/messaging/blink_transferable_message.h index 9478f639..be4743f0 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message.h +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.h
@@ -41,7 +41,7 @@ mojom::blink::DelegatedCapability delegated_capability = mojom::blink::DelegatedCapability::kNone; - std::optional<scheduler::TaskAttributionId> parent_task_id; + std::optional<scheduler::TaskAttributionId> task_state_id; }; CORE_EXPORT scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage(
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h index 0c4c8b59..122c464b 100644 --- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h +++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
@@ -66,11 +66,11 @@ return input.delegated_capability; } - static std::optional<blink::scheduler::TaskAttributionId> parent_task_id( + static std::optional<blink::scheduler::TaskAttributionId> task_state_id( blink::BlinkTransferableMessage& input) { - return input.parent_task_id + return input.task_state_id ? std::make_optional(blink::scheduler::TaskAttributionId( - input.parent_task_id.value())) + input.task_state_id.value())) : std::nullopt; }
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc index 898dde7..633b65de 100644 --- a/third_party/blink/renderer/core/messaging/message_port.cc +++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -135,22 +135,23 @@ msg.sender_agent_cluster_id = GetExecutionContext()->GetAgentClusterID(); msg.locked_to_sender_agent_cluster = msg.message->IsLockedToAgentCluster(); - // Only pass the parent task ID if we're in the main world, as isolated world - // task tracking is not yet supported. Also, only pass the parent task if the + // Only pass the task state ID if we're in the main world, as isolated world + // task tracking is not yet supported. Also, only pass the task state if the // port is still entangled to its initially entangled port. if (auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); initially_entangled_port_ && tracker && script_state->World().IsMainWorld()) { - if (scheduler::TaskAttributionInfo* task = tracker->RunningTask()) { + if (scheduler::TaskAttributionInfo* task_state = + tracker->CurrentTaskState()) { // Since `initially_entangled_port_` is not nullptr, neither should be // `post_message_task_container_`. CHECK(post_message_task_container_); - post_message_task_container_->AddPostMessageTask(task); - msg.parent_task_id = - std::optional<scheduler::TaskAttributionId>(task->Id()); + post_message_task_container_->AddPostMessageTask(task_state); + msg.task_state_id = + std::optional<scheduler::TaskAttributionId>(task_state->Id()); } else { - msg.parent_task_id = std::nullopt; + msg.task_state_id = std::nullopt; } } @@ -380,11 +381,11 @@ // Since `initially_entangled_port_` is not nullptr, neither should be // its `post_message_task_container_`. CHECK(entangled_port->post_message_task_container_); - scheduler::TaskAttributionInfo* parent_task = + scheduler::TaskAttributionInfo* task_state = entangled_port->post_message_task_container_ - ->GetAndDecrementPostMessageTask(message.parent_task_id); + ->GetAndDecrementPostMessageTask(message.task_state_id); task_attribution_scope = tracker->CreateTaskScope( - script_state, parent_task, + script_state, task_state, scheduler::TaskAttributionTracker::TaskScopeType::kPostMessage); } }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index 7308e81..027dbd9 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -50,6 +50,7 @@ #include "base/numerics/checked_math.h" #include "base/task/single_thread_task_runner.h" #include "cc/animation/animation_timeline.h" +#include "cc/base/features.h" #include "cc/input/main_thread_scrolling_reason.h" #include "cc/input/scroll_snap_data.h" #include "cc/input/scroll_utils.h" @@ -1372,6 +1373,24 @@ return ScrollHeight().Round() > client_height.Round(); } +bool PaintLayerScrollableArea::CanPropagateScroll() const { + if (!base::FeatureList::IsEnabled( + ::features::kOverscrollBehaviorRespectedOnAllScrollContainers)) { + return true; + } + auto* box = GetLayoutBox(); + // TODO(crbug.com/425353152): Remove the visibility check. + if (!box || !box->IsScrollContainer() || + box->StyleRef().Visibility() != EVisibility::kVisible) { + return true; + } + if (box->StyleRef().OverscrollBehaviorX() != EOverscrollBehavior::kAuto || + box->StyleRef().OverscrollBehaviorY() != EOverscrollBehavior::kAuto) { + return false; + } + return true; +} + // This function returns true if the given box requires overflow scrollbars (as // opposed to the viewport scrollbars managed by VisualViewport). static bool CanHaveOverflowScrollbars(const LayoutBox& box) { @@ -2555,6 +2574,8 @@ frame_view->RemoveScrollAnchoringScrollableArea(this); } + // TODO(crbug.com/425353152): Should be able to scroll invisible scroll + // containers. bool is_visible = GetLayoutBox()->StyleRef().Visibility() == EVisibility::kVisible; bool did_scroll_overflow = scrolls_overflow_; @@ -2568,6 +2589,17 @@ } scrolls_overflow_ = has_overflow && is_visible; + + if (GetLayoutBox()->IsScrollContainer() && !scrolls_overflow_ && + (GetLayoutBox()->StyleRef().OverscrollBehaviorX() != + EOverscrollBehavior::kAuto || + GetLayoutBox()->StyleRef().OverscrollBehaviorY() != + EOverscrollBehavior::kAuto)) { + UseCounter::Count( + GetLayoutBox()->GetDocument(), + WebFeature::kOverscrollBehaviorOnNonScrollableScrollContainer); + } + if (did_scroll_overflow == ScrollsOverflow()) return;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index 80a51f6..a46119f 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -555,6 +555,8 @@ bool HasHorizontalOverflow() const; bool HasVerticalOverflow() const; + bool CanPropagateScroll() const; + void Trace(Visitor*) const override; gfx::Rect ScrollingBackgroundVisualRect( @@ -921,6 +923,13 @@ HeapHashSet<Member<ScrollMarkerGroupData>> scroll_marker_group_data_set_; }; +template <> +struct DowncastTraits<PaintLayerScrollableArea> { + static bool AllowFrom(const ScrollableArea& from) { + return from.IsPaintLayerScrollableArea(); + } +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_LAYER_SCROLLABLE_AREA_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc index 81f348d6..ee378053 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -1228,6 +1228,65 @@ EXPECT_TRUE(GetDocument().IsUseCounted(WebFeature::kPositionSticky)); } +// Test when the observed behavior will change as a result of enabling +// OverscrollBehaviorRespectedOnAllScrollContainers. +TEST_P(PaintLayerScrollableAreaTest, + OverscrollBehaviorOnNonScrollableScrollContainerUseCounter) { + SetBodyInnerHTML(R"HTML( + <div id=scroller style="overflow: auto; width: 300px; height: 300px;"> + <div id=content style="width: 200px; height: 200px;"></div> + </div> + )HTML"); + + mojom::WebFeature feature = + WebFeature::kOverscrollBehaviorOnNonScrollableScrollContainer; + EXPECT_FALSE(GetDocument().IsUseCounted(feature)); + + auto* scroller = GetElementById("scroller"); + scroller->SetInlineStyleProperty(CSSPropertyID::kOverscrollBehaviorY, + CSSValueID::kNone); + UpdateAllLifecyclePhasesForTest(); + // If we have non-auto overscroll behavior on a non-scrollable scroll + // container, the behavior will be respected with the feature enabled. + EXPECT_TRUE(GetDocument().IsUseCounted(feature)); + EXPECT_EQ(scroller->ComputedStyleRef().OverscrollBehaviorX(), + EOverscrollBehavior::kAuto); + EXPECT_EQ(scroller->ComputedStyleRef().OverscrollBehaviorY(), + EOverscrollBehavior::kNone); + + GetDocument().ClearUseCounterForTesting(feature); + EXPECT_FALSE(GetDocument().IsUseCounted(feature)); + + scroller->SetInlineStyleProperty(CSSPropertyID::kOverflow, + CSSValueID::kHidden); + UpdateAllLifecyclePhasesForTest(); + // If we have non-auto overscroll behavior on a overflow: hidden scroll + // container, the behavior will be respected with the feature enabled. + EXPECT_TRUE(GetDocument().IsUseCounted(feature)); + EXPECT_EQ(scroller->ComputedStyleRef().OverflowX(), EOverflow::kHidden); + EXPECT_EQ(scroller->ComputedStyleRef().OverflowY(), EOverflow::kHidden); + + GetDocument().ClearUseCounterForTesting(feature); + EXPECT_FALSE(GetDocument().IsUseCounted(feature)); + + auto* content = GetElementById("content"); + content->SetInlineStyleProperty(CSSPropertyID::kWidth, "400px"); + UpdateAllLifecyclePhasesForTest(); + EXPECT_TRUE(GetDocument().IsUseCounted(feature)); + + GetDocument().ClearUseCounterForTesting(feature); + EXPECT_FALSE(GetDocument().IsUseCounted(feature)); + + scroller->SetInlineStyleProperty(CSSPropertyID::kOverscrollBehaviorY, + CSSValueID::kAuto); + UpdateAllLifecyclePhasesForTest(); + // If we have auto overscroll behavior on a scroll container, the behavior + // will not be affected with the feature enabled. + EXPECT_FALSE(GetDocument().IsUseCounted(feature)); + EXPECT_EQ(scroller->ComputedStyleRef().OverscrollBehaviorY(), + EOverscrollBehavior::kAuto); +} + // Delayed scroll offset clamping should not crash. https://crbug.com/842495 TEST_P(PaintLayerScrollableAreaTest, IgnoreDelayedScrollOnDestroyedLayer) { SetBodyInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index e65eb0a..25657f8 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -463,6 +463,9 @@ !scrollable_area->GetScrollOffset().IsZero()) { return true; } + if (!scrollable_area->CanPropagateScroll()) { + return true; + } return false; }
diff --git a/third_party/blink/renderer/core/scheduler/dom_scheduler.cc b/third_party/blink/renderer/core/scheduler/dom_scheduler.cc index 5e5de56c..6d39dccb 100644 --- a/third_party/blink/renderer/core/scheduler/dom_scheduler.cc +++ b/third_party/blink/renderer/core/scheduler/dom_scheduler.cc
@@ -233,7 +233,8 @@ if (auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate())) { // `task_state` is null if there's nothing to propagate. - if (scheduler::TaskAttributionInfo* task_state = tracker->RunningTask()) { + if (scheduler::TaskAttributionInfo* task_state = + tracker->CurrentTaskState()) { return task_state->Id().value(); } }
diff --git a/third_party/blink/renderer/core/scheduler/dom_task.cc b/third_party/blink/renderer/core/scheduler/dom_task.cc index 3d68cf34..cd1218a 100644 --- a/third_party/blink/renderer/core/scheduler/dom_task.cc +++ b/third_party/blink/renderer/core/scheduler/dom_task.cc
@@ -91,7 +91,7 @@ if (script_state->World().IsMainWorld()) { if (auto* tracker = scheduler::TaskAttributionTracker::From( script_state->GetIsolate())) { - parent_task_ = tracker->RunningTask(); + task_state_ = tracker->CurrentTaskState(); } } @@ -109,7 +109,7 @@ visitor->Trace(scheduler_task_context_); visitor->Trace(abort_handle_); visitor->Trace(task_queue_); - visitor->Trace(parent_task_); + visitor->Trace(task_state_); } void DOMTask::Invoke() { @@ -175,7 +175,7 @@ scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker) { task_attribution_scope = tracker->CreateTaskScope( - script_state, parent_task_, + script_state, task_state_, scheduler::TaskAttributionTracker::TaskScopeType::kSchedulerPostTask, scheduler_task_context_); } else {
diff --git a/third_party/blink/renderer/core/scheduler/dom_task.h b/third_party/blink/renderer/core/scheduler/dom_task.h index 5340120..3b12892 100644 --- a/third_party/blink/renderer/core/scheduler/dom_task.h +++ b/third_party/blink/renderer/core/scheduler/dom_task.h
@@ -69,7 +69,7 @@ const base::TimeDelta delay_; const uint64_t task_id_for_tracing_; ExecutionState execution_state_ = ExecutionState::kNotStarted; - Member<scheduler::TaskAttributionInfo> parent_task_; + Member<scheduler::TaskAttributionInfo> task_state_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/scheduler/scheduled_action.cc b/third_party/blink/renderer/core/scheduler/scheduled_action.cc index e9367a816..9254c4b9 100644 --- a/third_party/blink/renderer/core/scheduler/scheduled_action.cc +++ b/third_party/blink/renderer/core/scheduler/scheduled_action.cc
@@ -66,7 +66,7 @@ auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker && script_state->World().IsMainWorld()) { - function_->SetParentTask(tracker->RunningTask()); + function_->SetTaskState(tracker->CurrentTaskState()); } } else { UseCounter::Count(target, WebFeature::kScheduledActionIgnored); @@ -86,7 +86,7 @@ auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker && script_state->World().IsMainWorld()) { - code_parent_task_ = tracker->RunningTask(); + code_task_state_ = tracker->CurrentTaskState(); } } else { UseCounter::Count(target, WebFeature::kScheduledActionIgnored); @@ -163,7 +163,7 @@ scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker && script_state->World().IsMainWorld()) { task_attribution_scope = tracker->CreateTaskScope( - script_state, code_parent_task_, + script_state, code_task_state_, scheduler::TaskAttributionTracker::TaskScopeType::kScheduledAction); } @@ -182,7 +182,7 @@ visitor->Trace(script_state_); visitor->Trace(function_); visitor->Trace(arguments_); - visitor->Trace(code_parent_task_); + visitor->Trace(code_task_state_); } CallbackFunctionBase* ScheduledAction::CallbackFunction() {
diff --git a/third_party/blink/renderer/core/scheduler/scheduled_action.h b/third_party/blink/renderer/core/scheduler/scheduled_action.h index d5899311..ccf18ce 100644 --- a/third_party/blink/renderer/core/scheduler/scheduled_action.h +++ b/third_party/blink/renderer/core/scheduler/scheduled_action.h
@@ -83,7 +83,7 @@ Member<V8Function> function_; HeapVector<ScriptValue> arguments_; String code_; - Member<scheduler::TaskAttributionInfo> code_parent_task_; + Member<scheduler::TaskAttributionInfo> code_task_state_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.cc b/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.cc index fd65ca4..1372e5e 100644 --- a/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.cc +++ b/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.cc
@@ -64,7 +64,7 @@ CHECK(isolate_); } -scheduler::TaskAttributionInfo* TaskAttributionTrackerImpl::RunningTask() +scheduler::TaskAttributionInfo* TaskAttributionTrackerImpl::CurrentTaskState() const { if (ScriptWrappableTaskStateBase* task_state = ScriptWrappableTaskState::GetCurrent(isolate_)) { @@ -129,8 +129,8 @@ ? previous_unwrapped_task_state->GetTaskAttributionInfo() : nullptr; - // Fire observer callbacks after updating the CPED to keep `RunningTask()` in - // sync with what is passed to the observer. + // Fire observer callbacks after updating the CPED to keep + // `CurrentTaskState()` in sync with what is passed to the observer. // // TODO(crbug.com/40942324): The purpose of the `Observer` mechanism is so the // soft navigation layer can learn if an event ran while the scope is active, @@ -169,7 +169,7 @@ // the `observer_` since it relies on the callback to set up internal state. // And the `observer_` might not have been notified previously, e.g. if // the outermost `TaskScope` is for propagating soft navigation state. - TaskAttributionInfo* current_task_state = RunningTask(); + TaskAttributionInfo* current_task_state = CurrentTaskState(); if (observer_ && current_task_state) { observer_->OnCreateTaskScope(*current_task_state); }
diff --git a/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.h b/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.h index 4709643..7bf9b5cc 100644 --- a/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.h +++ b/third_party/blink/renderer/core/scheduler/task_attribution_tracker_impl.h
@@ -39,7 +39,7 @@ public: static std::unique_ptr<TaskAttributionTracker> Create(v8::Isolate*); - TaskAttributionInfo* RunningTask() const override; + TaskAttributionInfo* CurrentTaskState() const override; TaskScope CreateTaskScope(ScriptState* script_state, TaskAttributionInfo* task_state,
diff --git a/third_party/blink/renderer/core/scheduler/window_idle_tasks.cc b/third_party/blink/renderer/core/scheduler/window_idle_tasks.cc index 34cbede..0b48a93f 100644 --- a/third_party/blink/renderer/core/scheduler/window_idle_tasks.cc +++ b/third_party/blink/renderer/core/scheduler/window_idle_tasks.cc
@@ -42,7 +42,7 @@ auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (tracker && script_state->World().IsMainWorld()) { - parent_task_ = tracker->RunningTask(); + task_state_ = tracker->CurrentTaskState(); } auto* signal = DOMScheduler::scheduler(*scheduling_context) @@ -61,7 +61,7 @@ if (auto* tracker = scheduler::TaskAttributionTracker::From( script_state->GetIsolate())) { task_attribution_scope = - tracker->CreateTaskScope(script_state, parent_task_, + tracker->CreateTaskScope(script_state, task_state_, scheduler::TaskAttributionTracker:: TaskScopeType::kRequestIdleCallback, task_context_); @@ -71,14 +71,14 @@ void Trace(Visitor* visitor) const override { visitor->Trace(callback_); - visitor->Trace(parent_task_); + visitor->Trace(task_state_); visitor->Trace(task_context_); IdleTask::Trace(visitor); } private: Member<V8IdleRequestCallback> callback_; - Member<scheduler::TaskAttributionInfo> parent_task_; + Member<scheduler::TaskAttributionInfo> task_state_; Member<SchedulerTaskContext> task_context_; };
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc index 2e1eeaa5..ff4d738e 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -66,7 +66,7 @@ const TextEncoding& encoding, ScriptElementBase* element, FetchParameters::DeferOption defer, - scheduler::TaskAttributionInfo* parent_task) { + scheduler::TaskAttributionInfo* task_state) { ExecutionContext* context = element_document.GetExecutionContext(); FetchParameters params(options.CreateFetchParameters( url, context->GetSecurityOrigin(), context->GetCurrentWorld(), @@ -76,7 +76,7 @@ MakeGarbageCollected<ClassicPendingScript>( element, TextPosition::MinimumPosition(), KURL(), KURL(), String(), ScriptSourceLocationType::kExternalFile, options, - /*is_external=*/true, parent_task); + /*is_external=*/true, task_state); // [Intervention] // For users on slow connections, we want to avoid blocking the parser in @@ -121,11 +121,11 @@ const String& source_text, ScriptSourceLocationType source_location_type, const ScriptFetchOptions& options, - scheduler::TaskAttributionInfo* parent_task) { + scheduler::TaskAttributionInfo* task_state) { ClassicPendingScript* pending_script = MakeGarbageCollected<ClassicPendingScript>( element, starting_position, source_url, base_url, source_text, - source_location_type, options, /*is_external=*/false, parent_task); + source_location_type, options, /*is_external=*/false, task_state); pending_script->CheckState(); return pending_script; } @@ -139,8 +139,8 @@ ScriptSourceLocationType source_location_type, const ScriptFetchOptions& options, bool is_external, - scheduler::TaskAttributionInfo* parent_task) - : PendingScript(element, starting_position, parent_task), + scheduler::TaskAttributionInfo* task_state) + : PendingScript(element, starting_position, task_state), options_(options), source_url_for_inline_script_(source_url_for_inline_script), base_url_for_inline_script_(base_url_for_inline_script),
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.h b/third_party/blink/renderer/core/script/classic_pending_script.h index 3e156d1..76e0a45 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.h +++ b/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -42,7 +42,7 @@ const TextEncoding&, ScriptElementBase*, FetchParameters::DeferOption, - scheduler::TaskAttributionInfo* parent_task); + scheduler::TaskAttributionInfo* task_state); // For an inline script. static ClassicPendingScript* CreateInline(ScriptElementBase*, @@ -62,7 +62,7 @@ ScriptSourceLocationType, const ScriptFetchOptions&, bool is_external, - scheduler::TaskAttributionInfo* parent_task); + scheduler::TaskAttributionInfo* task_state); ~ClassicPendingScript() override; void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/core/script/module_pending_script.cc b/third_party/blink/renderer/core/script/module_pending_script.cc index b3936e8b..e2b385c9 100644 --- a/third_party/blink/renderer/core/script/module_pending_script.cc +++ b/third_party/blink/renderer/core/script/module_pending_script.cc
@@ -40,8 +40,8 @@ ScriptElementBase* element, ModulePendingScriptTreeClient* client, bool is_external, - scheduler::TaskAttributionInfo* parent_task) - : PendingScript(element, TextPosition::MinimumPosition(), parent_task), + scheduler::TaskAttributionInfo* task_state) + : PendingScript(element, TextPosition::MinimumPosition(), task_state), module_tree_client_(client), is_external_(is_external) { CHECK(GetElement());
diff --git a/third_party/blink/renderer/core/script/module_pending_script.h b/third_party/blink/renderer/core/script/module_pending_script.h index b8636724..69e1de7 100644 --- a/third_party/blink/renderer/core/script/module_pending_script.h +++ b/third_party/blink/renderer/core/script/module_pending_script.h
@@ -48,7 +48,7 @@ ModulePendingScript(ScriptElementBase*, ModulePendingScriptTreeClient*, bool is_external, - scheduler::TaskAttributionInfo* parent_task); + scheduler::TaskAttributionInfo* task_state); ~ModulePendingScript() override; void NotifyModuleTreeLoadFinished();
diff --git a/third_party/blink/renderer/core/script/pending_script.cc b/third_party/blink/renderer/core/script/pending_script.cc index 18e5eed..d659e39 100644 --- a/third_party/blink/renderer/core/script/pending_script.cc +++ b/third_party/blink/renderer/core/script/pending_script.cc
@@ -63,7 +63,7 @@ // about IsInDocumentWrite() use here. PendingScript::PendingScript(ScriptElementBase* element, const TextPosition& starting_position, - scheduler::TaskAttributionInfo* parent_task) + scheduler::TaskAttributionInfo* task_state) : element_(element), starting_position_(starting_position), virtual_time_pauser_(CreateWebScopedVirtualTimePauser(element)), @@ -72,7 +72,7 @@ original_execution_context_(element->GetExecutionContext()), created_during_document_write_( element->GetDocument().IsInDocumentWrite()), - parent_task_(parent_task) {} + task_state_(task_state) {} PendingScript::~PendingScript() {} @@ -169,7 +169,7 @@ if (auto* tracker = scheduler::TaskAttributionTracker::From( script_state->GetIsolate())) { task_attribution_scope = tracker->CreateTaskScope( - script_state, parent_task_, + script_state, task_state_, scheduler::TaskAttributionTracker::TaskScopeType::kScriptExecution); } } @@ -324,7 +324,7 @@ visitor->Trace(client_); visitor->Trace(original_execution_context_); visitor->Trace(original_element_document_); - visitor->Trace(parent_task_); + visitor->Trace(task_state_); } bool PendingScript::IsControlledByScriptRunner() const {
diff --git a/third_party/blink/renderer/core/script/pending_script.h b/third_party/blink/renderer/core/script/pending_script.h index cfb834eb..15deca7 100644 --- a/third_party/blink/renderer/core/script/pending_script.h +++ b/third_party/blink/renderer/core/script/pending_script.h
@@ -153,7 +153,7 @@ protected: PendingScript(ScriptElementBase*, const TextPosition& starting_position, - scheduler::TaskAttributionInfo* parent_task); + scheduler::TaskAttributionInfo* task_state); virtual void DisposeInternal() = 0; @@ -209,8 +209,8 @@ const bool created_during_document_write_; - // The ID of the parent task that loaded the script. - Member<scheduler::TaskAttributionInfo> parent_task_; + // The `TaskAttributionInfo` associated with the task that loaded the script. + Member<scheduler::TaskAttributionInfo> task_state_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index 9966efd..a58c7898d 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -90,13 +90,13 @@ namespace { -scheduler::TaskAttributionInfo* GetRunningTask(ScriptState* script_state) { +scheduler::TaskAttributionInfo* GetCurrentTaskState(ScriptState* script_state) { auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); if (!script_state || !script_state->World().IsMainWorld() || !tracker) { return nullptr; } - return tracker->RunningTask(); + return tracker->CurrentTaskState(); } } // namespace @@ -890,7 +890,7 @@ } ClassicPendingScript* pending_script = ClassicPendingScript::Fetch( url, element_document, options, cross_origin, encoding, element_, - defer, GetRunningTask(script_state)); + defer, GetCurrentTaskState(script_state)); prepared_pending_script_ = pending_script; Resource* resource = pending_script->GetResource(); resource_keep_alive_ = resource; @@ -1061,7 +1061,7 @@ prepared_pending_script_ = ClassicPendingScript::CreateInline( element_, position, source_url, base_url, source_text, - script_location_type, options, GetRunningTask(script_state)); + script_location_type, options, GetCurrentTaskState(script_state)); // <spec step="30.2.A.2">Mark as ready el given script.</spec> // @@ -1132,7 +1132,7 @@ network::mojom::RequestDestination::kScript, module_tree_client); prepared_pending_script_ = MakeGarbageCollected<ModulePendingScript>( element_, module_tree_client, is_external_script_, - GetRunningTask(script_state)); + GetCurrentTaskState(script_state)); break; } } @@ -1343,7 +1343,7 @@ ModuleImportPhase::kEvaluation); prepared_pending_script_ = MakeGarbageCollected<ModulePendingScript>( element_, module_tree_client, is_external_script_, - GetRunningTask(modulator->GetScriptState())); + GetCurrentTaskState(modulator->GetScriptState())); } PendingScript* ScriptLoader::TakePendingScript(
diff --git a/third_party/blink/renderer/core/script/script_runner_test.cc b/third_party/blink/renderer/core/script/script_runner_test.cc index da46f4b..fa143bc 100644 --- a/third_party/blink/renderer/core/script/script_runner_test.cc +++ b/third_party/blink/renderer/core/script/script_runner_test.cc
@@ -47,7 +47,7 @@ ScriptSchedulingType scheduling_type) : PendingScript(element, TextPosition::MinimumPosition(), - /*parent_task=*/nullptr) { + /*task_state=*/nullptr) { SetSchedulingType(scheduling_type); } ~MockPendingScript() override {}
diff --git a/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc b/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc index e853e7e4..caa518f0 100644 --- a/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc +++ b/third_party/blink/renderer/core/scroll/scroll_into_view_util.cc
@@ -77,19 +77,6 @@ return !from_frame.GetDocument()->IsVerticalScrollEnforced(); } -ALWAYS_INLINE ScrollableArea* GetScrollableAreaForLayoutBox( - const LayoutBox& box, - const mojom::blink::ScrollIntoViewParamsPtr& params) { - if (box.IsScrollContainer() && !box.IsLayoutView()) { - return box.GetScrollableArea(); - } else if (!box.ContainingBlock()) { - return params->make_visible_in_visual_viewport - ? box.GetFrameView()->GetScrollableArea() - : box.GetFrameView()->LayoutViewport(); - } - return nullptr; -} - // Helper to return the parent LayoutBox, crossing local frame boundaries, that // a scroll should bubble up to or nullptr if the local root has been reached. // The return optional will be empty if the scroll is blocked from bubbling to @@ -218,7 +205,8 @@ ScrollableArea* area_to_scroll = nullptr; if (include_self || current_box != &box) { - area_to_scroll = GetScrollableAreaForLayoutBox(*current_box, params); + area_to_scroll = scroll_into_view_util::GetScrollableAreaForLayoutBox( + *current_box, params->make_visible_in_visual_viewport); } if (area_to_scroll) { ScrollOffset scroll_before = area_to_scroll->GetScrollOffset(); @@ -335,6 +323,19 @@ namespace scroll_into_view_util { +ScrollableArea* GetScrollableAreaForLayoutBox( + const LayoutBox& box, + bool make_visible_in_visual_viewport) { + if (box.IsScrollContainer() && !box.IsLayoutView()) { + return box.GetScrollableArea(); + } else if (!box.ContainingBlock()) { + return make_visible_in_visual_viewport + ? box.GetFrameView()->GetScrollableArea() + : box.GetFrameView()->LayoutViewport(); + } + return nullptr; +} + void ScrollRectToVisible(const LayoutObject& layout_object, const PhysicalRect& absolute_rect, mojom::blink::ScrollIntoViewParamsPtr params,
diff --git a/third_party/blink/renderer/core/scroll/scroll_into_view_util.h b/third_party/blink/renderer/core/scroll/scroll_into_view_util.h index 891f751..abef786 100644 --- a/third_party/blink/renderer/core/scroll/scroll_into_view_util.h +++ b/third_party/blink/renderer/core/scroll/scroll_into_view_util.h
@@ -22,6 +22,7 @@ class LayoutObject; class LayoutView; +class LayoutBox; struct PhysicalRect; class ScrollableArea; class ComputedStyle; @@ -68,6 +69,10 @@ const mojom::blink::ScrollAlignment& align_x, const mojom::blink::ScrollAlignment& align_y); +ScrollableArea* GetScrollableAreaForLayoutBox( + const LayoutBox& box, + bool make_visible_in_visual_viewport); + mojom::blink::ScrollAlignment ResolveToPhysicalAlignment( V8ScrollLogicalPosition::Enum inline_alignment, V8ScrollLogicalPosition::Enum block_alignment,
diff --git a/third_party/blink/renderer/core/scroll/scrollbar_theme.cc b/third_party/blink/renderer/core/scroll/scrollbar_theme.cc index 29d25f3..e8b77c2d 100644 --- a/third_party/blink/renderer/core/scroll/scrollbar_theme.cc +++ b/third_party/blink/renderer/core/scroll/scrollbar_theme.cc
@@ -303,7 +303,6 @@ const gfx::Rect& rect) { // CustomScrollbarTheme must override this method. DCHECK(!scrollbar.IsCustomScrollbar()); - CHECK_EQ(rect.size(), scrollbar.FrameRect().size()); gfx::Vector2d offset = rect.origin() - scrollbar.Location(); if (DrawingRecorder::UseCachedDrawingIfPossible(
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc index b6207f9..1fe3df5 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -196,6 +196,21 @@ return features::SoftNavigationHeuristicsMode::kBasic; } +SoftNavigationHeuristics* GetHeuristicsForNodeIfShouldTrack(const Node& node) { + const Document& document = node.GetDocument(); + if (!document.IsTrackingSoftNavigationHeuristics()) { + return nullptr; + } + if (!node.isConnected()) { + return nullptr; + } + LocalDOMWindow* window = document.domWindow(); + if (!window) { + return nullptr; + } + return window->GetSoftNavigationHeuristics(); +} + } // namespace SoftNavigationHeuristics::SoftNavigationHeuristics(LocalDOMWindow* window) @@ -267,7 +282,7 @@ // The `task_attribution_tracker_` must exist if `potential_soft_navigations_` // is non-empty. `task_state` can have null `context` in tests. CHECK(task_attribution_tracker_); - if (auto* task_state = task_attribution_tracker_->RunningTask()) { + if (auto* task_state = task_attribution_tracker_->CurrentTaskState()) { return EnsureContextForCurrentWindow( task_state->GetSoftNavigationContext()); } @@ -282,7 +297,7 @@ return std::nullopt; } scheduler::TaskAttributionInfo* task_state = - task_attribution_tracker_->RunningTask(); + task_attribution_tracker_->CurrentTaskState(); if (!task_state) { return std::nullopt; } @@ -704,6 +719,30 @@ return kMinRequiredArea; } +// static +void SoftNavigationHeuristics::InsertedNode(Node* inserted_node, + Node* container_node) { + auto* heuristics = GetHeuristicsForNodeIfShouldTrack(*inserted_node); + if (!heuristics) { + return; + } + // When a child node, which is an HTML-element, is modified within a parent + // (added, moved, etc), mark that child as modified by soft navigation. + // Otherwise, if the child is not an HTML-element, mark the parent instead. + // TODO(crbug.com/41494072): This does not filter out updates from isolated + // worlds. Should it? + heuristics->ModifiedDOM(inserted_node->IsHTMLElement() ? inserted_node + : container_node); +} + +void SoftNavigationHeuristics::ModifiedNode(Node* node) { + auto* heuristics = GetHeuristicsForNodeIfShouldTrack(*node); + if (!heuristics) { + return; + } + heuristics->ModifiedDOM(node); +} + // SoftNavigationHeuristics::EventScope implementation // /////////////////////////////////////////// SoftNavigationHeuristics::EventScope::EventScope(
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h index 79d4e96..1266bf64 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h
@@ -80,6 +80,16 @@ static SoftNavigationHeuristics* CreateIfNeeded(LocalDOMWindow*); + // Inform `SoftNavigationHeuristics` that `inserted_node` was inserted into + // `container_node`. Sets up paint tracking if the modification is + // attributable to a `SoftNavigationContext` and connected to the DOM. + static void InsertedNode(Node* inserted_node, Node* container_node); + + // Inform `SoftNavigationHeuristics` that `node` was modified in some way. + // Sets up paint tracking if the modification is attributable to a + // `SoftNavigationContext` and connected to the DOM. + static void ModifiedNode(Node* node); + // GarbageCollected boilerplate. void Trace(Visitor*) const override;
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc index 593d2d0..d5d460e 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics_test.cc
@@ -143,7 +143,7 @@ scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); ASSERT_TRUE(tracker); - Persistent<scheduler::TaskAttributionInfo> root_task = nullptr; + Persistent<scheduler::TaskAttributionInfo> root_task_state = nullptr; // Simulate a click. { EXPECT_FALSE(IsDocumentTrackingSoftNavigations()); @@ -159,24 +159,24 @@ // stack to propagate the soft navigation context, but it should notify // `heuristics`. EXPECT_FALSE(task_scope); - root_task = tracker->RunningTask(); + root_task_state = tracker->CurrentTaskState(); } - EXPECT_TRUE(root_task); + EXPECT_TRUE(root_task_state); EXPECT_TRUE(IsDocumentTrackingSoftNavigations()); // Simulate a descendant task. - Persistent<scheduler::TaskAttributionInfo> descendant_task = nullptr; + Persistent<scheduler::TaskAttributionInfo> descendant_task_state = nullptr; { - TaskScope task_scope = tracker->CreateTaskScope(script_state, root_task, - TaskScopeType::kCallback); - descendant_task = tracker->RunningTask(); + TaskScope task_scope = tracker->CreateTaskScope( + script_state, root_task_state, TaskScopeType::kCallback); + descendant_task_state = tracker->CurrentTaskState(); } - EXPECT_TRUE(descendant_task); + EXPECT_TRUE(descendant_task_state); EXPECT_TRUE(IsDocumentTrackingSoftNavigations()); - EXPECT_EQ(root_task.Get(), descendant_task.Get()); + EXPECT_EQ(root_task_state.Get(), descendant_task_state.Get()); - root_task = nullptr; + root_task_state = nullptr; ThreadState::Current()->CollectAllGarbageForTesting(); // The heuristics still should not have been reset since there is a live // root task, which is being held onto by its descendant task. @@ -184,7 +184,7 @@ // Finally, this should allow the click task to be GCed, which should cause // the heuristics to be reset. - descendant_task = nullptr; + descendant_task_state = nullptr; ThreadState::Current()->CollectAllGarbageForTesting(); EXPECT_FALSE(IsDocumentTrackingSoftNavigations()); } @@ -204,7 +204,7 @@ { std::optional<TaskScope> task_scope = tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); - context1 = tracker->RunningTask()->GetSoftNavigationContext(); + context1 = tracker->CurrentTaskState()->GetSoftNavigationContext(); } EXPECT_TRUE(context1); @@ -217,7 +217,7 @@ { std::optional<TaskScope> task_scope = tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); - context2 = tracker->RunningTask()->GetSoftNavigationContext(); + context2 = tracker->CurrentTaskState()->GetSoftNavigationContext(); } EXPECT_TRUE(context2); @@ -236,7 +236,7 @@ scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); ASSERT_TRUE(tracker); - auto* context = tracker->RunningTask()->GetSoftNavigationContext(); + auto* context = tracker->CurrentTaskState()->GetSoftNavigationContext(); ASSERT_TRUE(context); { @@ -328,7 +328,7 @@ heuristics->MaybeCreateEventScopeForEvent(*event)); std::optional<TaskScope> task_scope = tracker->MaybeCreateTaskScopeForCallback(script_state, nullptr); - task_state = tracker->RunningTask(); + task_state = tracker->CurrentTaskState(); ASSERT_TRUE(task_state); context = task_state->GetSoftNavigationContext(); ASSERT_TRUE(context); @@ -358,7 +358,7 @@ { std::optional<TaskScope> task_scope = tracker->MaybeCreateTaskScopeForCallback(script_state, task_state); - EXPECT_EQ(tracker->RunningTask()->GetSoftNavigationContext(), context); + EXPECT_EQ(tracker->CurrentTaskState()->GetSoftNavigationContext(), context); heuristics->SameDocumentNavigationCommitted("bar.html", context); heuristics->ModifiedDOM(node2); } @@ -397,7 +397,7 @@ CreateEvent(SoftNavigationHeuristics::EventScope::Type::kClick); std::optional<SoftNavigationHeuristics::EventScope> event_scope( heuristics->MaybeCreateEventScopeForEvent(*event)); - task_state = tracker->RunningTask(); + task_state = tracker->CurrentTaskState(); ASSERT_TRUE(task_state); context = task_state->GetSoftNavigationContext(); ASSERT_TRUE(context);
diff --git a/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc b/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc index 56d1454..8470f80 100644 --- a/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc +++ b/third_party/blink/renderer/core/view_transition/view_transition_supplement.cc
@@ -65,10 +65,10 @@ if (callback) { auto* tracker = scheduler::TaskAttributionTracker::From(script_state->GetIsolate()); - // Set the parent task ID if we're not in an extension task (as extensions + // Set the task state if we're not in an extension task (as extensions // are not currently supported in TaskAttributionTracker). if (tracker && script_state->World().IsMainWorld()) { - callback->SetParentTask(tracker->RunningTask()); + callback->SetTaskState(tracker->CurrentTaskState()); } } return supplement->StartTransition(*element, callback, types,
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc index fe0ba59..6fc519b 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -657,7 +657,7 @@ state_ = kUnsent; error_ = false; upload_complete_ = false; - parent_task_ = nullptr; + task_state_ = nullptr; auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext()); if (!async && window) { @@ -1013,7 +1013,7 @@ if (world_ && world_->IsMainWorld()) { if (auto* tracker = scheduler::TaskAttributionTracker::From( execution_context.GetIsolate())) { - parent_task_ = tracker->RunningTask(); + task_state_ = tracker->CurrentTaskState(); } } async_task_context_.Schedule(&execution_context, "XMLHttpRequest.send"); @@ -1344,7 +1344,7 @@ DispatchProgressEvent(event_type_names::kLoadend, /*received_length=*/0, /*expected_length=*/0); - parent_task_ = nullptr; + task_state_ = nullptr; } // https://xhr.spec.whatwg.org/#the-overridemimetype()-method @@ -1789,7 +1789,7 @@ frame->GetPage()->GetChromeClient().AjaxSucceeded(frame); } - parent_task_ = nullptr; + task_state_ = nullptr; } void XMLHttpRequest::DidSendData(uint64_t bytes_sent, @@ -2068,7 +2068,7 @@ visitor->Trace(world_); visitor->Trace(upload_); visitor->Trace(blob_loader_); - visitor->Trace(parent_task_); + visitor->Trace(task_state_); XMLHttpRequestEventTarget::Trace(visitor); ThreadableLoaderClient::Trace(visitor); DocumentParserClient::Trace(visitor); @@ -2081,11 +2081,11 @@ std::optional<scheduler::TaskAttributionTracker::TaskScope> XMLHttpRequest::MaybeCreateTaskAttributionScope() { - if (!parent_task_ || !GetExecutionContext() || + if (!task_state_ || !GetExecutionContext() || GetExecutionContext()->IsContextDestroyed()) { return std::nullopt; } - // `parent_task_` being non-null implies that task tracking is enabled and + // `task_state_` being non-null implies that task tracking is enabled and // this object is associated with the main world. auto* script_state = ToScriptStateForMainWorld(GetExecutionContext()); CHECK(script_state); @@ -2098,11 +2098,11 @@ // // TODO(crbug.com/1439971): Make this safe to do or move the logic into the // task attribution implementation. - if (tracker->RunningTask() == parent_task_.Get()) { + if (tracker->CurrentTaskState() == task_state_.Get()) { return std::nullopt; } return tracker->CreateTaskScope( - script_state, parent_task_, + script_state, task_state_, scheduler::TaskAttributionTracker::TaskScopeType::kXMLHttpRequest); }
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h index 872c41e..8ce7bad 100644 --- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h +++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.h
@@ -294,7 +294,7 @@ // so there is no need. void ReportMemoryUsageToV8(); - // Creates a task scope used for firing events if the `parent_task_` is set + // Creates a task scope used for firing events if the `task_state_` is set // and different from the current task. std::optional<scheduler::TaskAttributionTracker::TaskScope> MaybeCreateTaskAttributionScope(); @@ -364,7 +364,7 @@ // |m_responseTypeCode| is NOT ResponseTypeBlob. Member<BlobLoader> blob_loader_; - Member<scheduler::TaskAttributionInfo> parent_task_; + Member<scheduler::TaskAttributionInfo> task_state_; bool async_ = true;
diff --git a/third_party/blink/renderer/modules/ai/ai_utils.h b/third_party/blink/renderer/modules/ai/ai_utils.h index 96acf3e..f2df447 100644 --- a/third_party/blink/renderer/modules/ai/ai_utils.h +++ b/third_party/blink/renderer/modules/ai/ai_utils.h
@@ -12,11 +12,13 @@ #include "third_party/blink/public/mojom/ai/ai_rewriter.mojom-blink.h" #include "third_party/blink/public/mojom/ai/ai_summarizer.mojom-blink.h" #include "third_party/blink/public/mojom/ai/ai_writer.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_proofreader_create_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rewriter_create_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_summarizer_create_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_writer_create_options.h" +#include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/modules/ai/availability.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -138,6 +140,26 @@ base::OnceClosure callback_; }; +// Returns a closure that rejects `resolver` if it's destroyed before being run. +// If `signal` is aborted on destruction, its reason is passed with rejection. +template <typename T> +base::OnceClosure RejectOnDestruction(ScriptPromiseResolver<T>* resolver, + AbortSignal* signal = nullptr) { + RunOnDestruction run_on_destruction(WTF::BindOnce( + [](ScriptPromiseResolver<T>* resolver, AbortSignal* signal) { + if (signal && signal->aborted()) { + resolver->Reject(signal->reason(resolver->GetScriptState())); + } else { + resolver->Reject(); + } + }, + WrapPersistent(resolver), WrapPersistent(signal))); + + return WTF::BindOnce( + [](RunOnDestruction resolver_holder) { resolver_holder.Reset(); }, + std::move(run_on_destruction)); +} + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_AI_AI_UTILS_H_
diff --git a/third_party/blink/renderer/modules/ai/ai_writing_assistance_base.h b/third_party/blink/renderer/modules/ai/ai_writing_assistance_base.h index fd9674d..2fd28ad4 100644 --- a/third_party/blink/renderer/modules/ai/ai_writing_assistance_base.h +++ b/third_party/blink/renderer/modules/ai/ai_writing_assistance_base.h
@@ -13,6 +13,7 @@ #include "third_party/blink/public/mojom/ai/ai_common.mojom-blink.h" #include "third_party/blink/public/mojom/ai/model_streaming_responder.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/core/dom/abort_controller.h" #include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" @@ -95,24 +96,36 @@ typename ExecuteOptions> class AIWritingAssistanceBase : public ExecutionContextClient { public: - AIWritingAssistanceBase(ExecutionContext* execution_context, + AIWritingAssistanceBase(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<AIMojoClient> pending_remote, CreateOptions* options, bool echo_whitespace_input) - : ExecutionContextClient(execution_context), - remote_(execution_context), + : ExecutionContextClient(ExecutionContext::From(script_state)), + remote_(GetExecutionContext()), options_(options), + destruction_abort_controller_(AbortController::Create(script_state)), + create_abort_signal_(options->getSignalOr(nullptr)), task_runner_(std::move(task_runner)), metric_session_type_(GetSessionType()), echo_whitespace_input_(echo_whitespace_input) { remote_.Bind(std::move(pending_remote), task_runner_); + + if (create_abort_signal_) { + CHECK(!create_abort_signal_->aborted()); + create_abort_handle_ = create_abort_signal_->AddAlgorithm(WTF::BindOnce( + &AIWritingAssistanceBase::OnCreateAbortSignalAborted, + WrapWeakPersistent(this), WrapWeakPersistent(script_state))); + } } void Trace(Visitor* visitor) const override { ExecutionContextClient::Trace(visitor); visitor->Trace(remote_); visitor->Trace(options_); + visitor->Trace(destruction_abort_controller_); + visitor->Trace(create_abort_signal_); + visitor->Trace(create_abort_handle_); } static ScriptPromise<V8Availability> availability( @@ -177,16 +190,15 @@ return ScriptPromise<V8SessionObjectType>(); } + AbortSignal* signal = options->getSignalOr(nullptr); + if (HandleAbortSignal(signal, script_state, exception_state)) { + return EmptyPromise(); + } + auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<V8SessionObjectType>>( script_state); auto promise = resolver->Promise(); - AbortSignal* signal = options->getSignalOr(nullptr); - if (signal && signal->aborted()) { - resolver->Reject(signal->reason(script_state)); - return promise; - } - ExecutionContext* execution_context = ExecutionContext::From(script_state); // Block access if the Permission Policy is not enabled. @@ -221,6 +233,14 @@ ThrowInvalidContextException(exception_state); return ScriptPromise<IDLString>(); } + + CHECK(options); + AbortSignal* composite_signal = + CreateCompositeSignal(script_state, options); + if (HandleAbortSignal(composite_signal, script_state, exception_state)) { + return EmptyPromise(); + } + if (!remote_) { ThrowSessionDestroyedException(exception_state); return ScriptPromise<IDLString>(); @@ -233,17 +253,10 @@ AIMetrics::GetAISessionRequestSizeMetricName(metric_session_type_), static_cast<int>(input.CharactersSizeInBytes())); - CHECK(options); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<IDLString>>(script_state); auto promise = resolver->Promise(); - AbortSignal* signal = options->getSignalOr(nullptr); - if (signal && signal->aborted()) { - resolver->Reject(signal->reason(script_state)); - return promise; - } - String trimmed_input = input.StripWhiteSpace(); if (trimmed_input.empty()) { resolver->Resolve(echo_whitespace_input_ ? input : trimmed_input); @@ -254,7 +267,8 @@ options->getContextOr(g_empty_string).StripWhiteSpace(); // Pass persistent refs to keep this instance alive during the response. auto pending_remote = CreateModelExecutionResponder( - script_state, signal, resolver, task_runner_, metric_session_type_, + script_state, composite_signal, resolver, task_runner_, + metric_session_type_, base::DoNothingWithBoundArgs(WrapPersistent(this)), base::DoNothingWithBoundArgs(WrapPersistent(this)), /*resolve_override_callback=*/base::NullCallback()); @@ -273,6 +287,14 @@ ThrowInvalidContextException(exception_state); return nullptr; } + + CHECK(options); + AbortSignal* composite_signal = + CreateCompositeSignal(script_state, options); + if (HandleAbortSignal(composite_signal, script_state, exception_state)) { + return nullptr; + } + if (!remote_) { ThrowSessionDestroyedException(exception_state); return nullptr; @@ -285,12 +307,6 @@ AIMetrics::GetAISessionRequestSizeMetricName(metric_session_type_), static_cast<int>(input.CharactersSizeInBytes())); - CHECK(options); - AbortSignal* signal = options->getSignalOr(nullptr); - if (HandleAbortSignal(signal, script_state, exception_state)) { - return nullptr; - } - String trimmed_input = input.StripWhiteSpace(); if (trimmed_input.empty()) { return CreateEmptyReadableStream(script_state, metric_session_type_); @@ -301,7 +317,7 @@ // Pass persistent refs to keep this instance alive during the response. auto [readable_stream, pending_remote] = CreateModelExecutionStreamingResponder( - script_state, signal, task_runner_, metric_session_type_, + script_state, composite_signal, task_runner_, metric_session_type_, base::DoNothingWithBoundArgs(WrapPersistent(this)), base::DoNothingWithBoundArgs(WrapPersistent(this))); remoteExecute(trimmed_input, trimmed_context, std::move(pending_remote)); @@ -317,6 +333,13 @@ return ScriptPromise<IDLDouble>(); } + CHECK(options); + AbortSignal* composite_signal = + CreateCompositeSignal(script_state, options); + if (HandleAbortSignal(composite_signal, script_state, exception_state)) { + return EmptyPromise(); + } + if (!remote_) { ThrowSessionDestroyedException(exception_state); return ScriptPromise<IDLDouble>(); @@ -325,12 +348,7 @@ auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<IDLDouble>>(script_state); auto promise = resolver->Promise(); - CHECK(options); - AbortSignal* signal = options->getSignalOr(nullptr); - if (signal && signal->aborted()) { - resolver->Reject(signal->reason(script_state)); - return promise; - } + auto reject_fn = RejectOnDestruction(resolver, composite_signal); remote_->MeasureUsage( input, options->getContextOr(g_empty_string), @@ -354,8 +372,8 @@ } resolver->Resolve(static_cast<double>(usage.value())); }, - WrapPersistent(resolver), - WrapPersistent(options->getSignalOr(nullptr)))); + WrapPersistent(resolver), WrapPersistent(composite_signal)) + .Then(std::move(reject_fn))); return promise; } @@ -370,7 +388,8 @@ AIMetrics::GetAIAPIUsageMetricName(metric_session_type_), AIMetrics::AIAPI::kSessionDestroy); - remote_.reset(); + destruction_abort_controller_->abort(script_state); + DestroyImpl(); } String sharedContext() const { @@ -430,6 +449,37 @@ Member<CreateOptions> options_; private: + void DestroyImpl() { + remote_.reset(); + + if (create_abort_handle_) { + create_abort_signal_->RemoveAlgorithm(create_abort_handle_); + create_abort_handle_ = nullptr; + } + } + + void OnCreateAbortSignalAborted(ScriptState* script_state) { + if (script_state) { + destruction_abort_controller_->abort( + script_state, create_abort_signal_->reason(script_state)); + } + DestroyImpl(); + } + + AbortSignal* CreateCompositeSignal(ScriptState* script_state, + const ExecuteOptions* options) { + HeapVector<Member<AbortSignal>> signals; + + signals.push_back(destruction_abort_controller_->signal()); + + CHECK(options); + if (options->hasSignal()) { + signals.push_back(options->signal()); + } + + return MakeGarbageCollected<AbortSignal>(script_state, signals); + } + static bool ValidateAndCanonicalizeOptionLanguages( v8::Isolate* isolate, CreateCoreOptions* options) { @@ -463,8 +513,20 @@ return true; } + // Abort controller triggered on destroy() or when create abort signal is + // executed. + Member<AbortController> destruction_abort_controller_; + + // Abort signal passed to CreateOptions. + Member<AbortSignal> create_abort_signal_; + + // Handle to hold create_abort_signal_ callback, which is run when aborted. + Member<AbortSignal::AlgorithmHandle> create_abort_handle_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; + AIMetrics::AISessionType metric_session_type_; + // Whether to echo back the original input if it only contains whitespace. // If false, it returns an empty string. bool echo_whitespace_input_;
diff --git a/third_party/blink/renderer/modules/ai/ai_writing_assistance_create_client.h b/third_party/blink/renderer/modules/ai/ai_writing_assistance_create_client.h index aa999d4..cb8ab5c3 100644 --- a/third_party/blink/renderer/modules/ai/ai_writing_assistance_create_client.h +++ b/third_party/blink/renderer/modules/ai/ai_writing_assistance_create_client.h
@@ -112,9 +112,9 @@ } } - if (GetExecutionContext() && pending_remote) { + if (pending_remote) { this->GetResolver()->Resolve(MakeGarbageCollected<V8SessionObjectType>( - GetExecutionContext(), task_runner_, std::move(pending_remote), + this->GetScriptState(), task_runner_, std::move(pending_remote), options_)); } else { this->GetResolver()->RejectWithDOMException(
diff --git a/third_party/blink/renderer/modules/ai/model_execution_responder.cc b/third_party/blink/renderer/modules/ai/model_execution_responder.cc index 38b7a251..f219c2a 100644 --- a/third_party/blink/renderer/modules/ai/model_execution_responder.cc +++ b/third_party/blink/renderer/modules/ai/model_execution_responder.cc
@@ -271,7 +271,6 @@ } RecordResponseMetrics(); Cleanup(); - return; } void OnError(ModelStreamingResponseStatus status,
diff --git a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc index d35d8ae..440fd8e 100644 --- a/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc +++ b/third_party/blink/renderer/modules/ai/on_device_translation/language_detector.cc
@@ -58,18 +58,6 @@ } } -// Rejects if the OnceClosure is destroyed before it is ran. -template <typename T> -base::OnceClosure RejectOnDestruction(ScriptPromiseResolver<T>* resolver) { - RunOnDestruction run_on_destruction(WTF::BindOnce( - [](ScriptPromiseResolver<T>* resolver) { resolver->Reject(); }, - WrapPersistent(resolver))); - - return WTF::BindOnce( - [](RunOnDestruction resolver_holder) { resolver_holder.Reset(); }, - std::move(run_on_destruction)); -} - class LanguageDetectorCreateTask : public GarbageCollected<LanguageDetectorCreateTask>, public ExecutionContextClient,
diff --git a/third_party/blink/renderer/modules/ai/proofreader.cc b/third_party/blink/renderer/modules/ai/proofreader.cc index 62fee13..8224b0e 100644 --- a/third_party/blink/renderer/modules/ai/proofreader.cc +++ b/third_party/blink/renderer/modules/ai/proofreader.cc
@@ -42,12 +42,12 @@ } Proofreader::Proofreader( - ExecutionContext* execution_context, + ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIProofreader> pending_remote, ProofreaderCreateOptions* options) - : ExecutionContextClient(execution_context), - remote_(execution_context), + : ExecutionContextClient(ExecutionContext::From(script_state)), + remote_(GetExecutionContext()), options_(std::move(options)), task_runner_(std::move(task_runner)) { remote_.Bind(std::move(pending_remote), task_runner_); @@ -75,8 +75,7 @@ } auto* resolver = - MakeGarbageCollected<ScriptPromiseResolver<V8Availability>>( - script_state); + MakeGarbageCollected<ScriptPromiseResolver<V8Availability>>(script_state); auto promise = resolver->Promise(); ExecutionContext* execution_context = ExecutionContext::From(script_state); @@ -206,9 +205,9 @@ return; } - base::UmaHistogramEnumeration( - AIMetrics::GetAIAPIUsageMetricName(AIMetrics::AISessionType::kProofreader), - AIMetrics::AIAPI::kSessionDestroy); + base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( + AIMetrics::AISessionType::kProofreader), + AIMetrics::AIAPI::kSessionDestroy); remote_.reset(); }
diff --git a/third_party/blink/renderer/modules/ai/proofreader.h b/third_party/blink/renderer/modules/ai/proofreader.h index b925513..434d685 100644 --- a/third_party/blink/renderer/modules/ai/proofreader.h +++ b/third_party/blink/renderer/modules/ai/proofreader.h
@@ -30,7 +30,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - Proofreader(ExecutionContext* execution_context, + Proofreader(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIProofreader> pending_remote, ProofreaderCreateOptions* options);
diff --git a/third_party/blink/renderer/modules/ai/rewriter.cc b/third_party/blink/renderer/modules/ai/rewriter.cc index e0e30a6b6..529fe82 100644 --- a/third_party/blink/renderer/modules/ai/rewriter.cc +++ b/third_party/blink/renderer/modules/ai/rewriter.cc
@@ -147,7 +147,7 @@ } } -Rewriter::Rewriter(ExecutionContext* execution_context, +Rewriter::Rewriter(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIRewriter> pending_remote, RewriterCreateOptions* options) @@ -157,7 +157,7 @@ RewriterCreateCoreOptions, RewriterCreateOptions, RewriterRewriteOptions>( - execution_context, + script_state, task_runner, std::move(pending_remote), std::move(options),
diff --git a/third_party/blink/renderer/modules/ai/rewriter.h b/third_party/blink/renderer/modules/ai/rewriter.h index 23b0b15..aa0a516 100644 --- a/third_party/blink/renderer/modules/ai/rewriter.h +++ b/third_party/blink/renderer/modules/ai/rewriter.h
@@ -27,7 +27,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - Rewriter(ExecutionContext* execution_context, + Rewriter(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIRewriter> pending_remote, RewriterCreateOptions* options);
diff --git a/third_party/blink/renderer/modules/ai/summarizer.cc b/third_party/blink/renderer/modules/ai/summarizer.cc index 6d88761..66319202 100644 --- a/third_party/blink/renderer/modules/ai/summarizer.cc +++ b/third_party/blink/renderer/modules/ai/summarizer.cc
@@ -149,7 +149,7 @@ } Summarizer::Summarizer( - ExecutionContext* execution_context, + ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AISummarizer> pending_remote, SummarizerCreateOptions* options) @@ -159,7 +159,7 @@ SummarizerCreateCoreOptions, SummarizerCreateOptions, SummarizerSummarizeOptions>( - execution_context, + script_state, task_runner, std::move(pending_remote), std::move(options),
diff --git a/third_party/blink/renderer/modules/ai/summarizer.h b/third_party/blink/renderer/modules/ai/summarizer.h index c8e0a4c0..f0ca841 100644 --- a/third_party/blink/renderer/modules/ai/summarizer.h +++ b/third_party/blink/renderer/modules/ai/summarizer.h
@@ -27,7 +27,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - Summarizer(ExecutionContext* execution_context, + Summarizer(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AISummarizer> pending_remote, SummarizerCreateOptions* options);
diff --git a/third_party/blink/renderer/modules/ai/writer.cc b/third_party/blink/renderer/modules/ai/writer.cc index caa43fc..2dbe8b9 100644 --- a/third_party/blink/renderer/modules/ai/writer.cc +++ b/third_party/blink/renderer/modules/ai/writer.cc
@@ -142,7 +142,7 @@ } } -Writer::Writer(ExecutionContext* execution_context, +Writer::Writer(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIWriter> pending_remote, WriterCreateOptions* options) @@ -152,7 +152,7 @@ WriterCreateCoreOptions, WriterCreateOptions, WriterWriteOptions>( - execution_context, + script_state, task_runner, std::move(pending_remote), std::move(options),
diff --git a/third_party/blink/renderer/modules/ai/writer.h b/third_party/blink/renderer/modules/ai/writer.h index 1ce3ace..9129a302 100644 --- a/third_party/blink/renderer/modules/ai/writer.h +++ b/third_party/blink/renderer/modules/ai/writer.h
@@ -27,7 +27,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - Writer(ExecutionContext* execution_context, + Writer(ScriptState* script_state, scoped_refptr<base::SequencedTaskRunner> task_runner, mojo::PendingRemote<mojom::blink::AIWriter> pending_remote, WriterCreateOptions* options);
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc index bca81e6..3913bbb 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -778,9 +778,10 @@ // TODO(crbug.com/421834883): This code is based on image drawing. Maybe we // need a distinct paint_type: kImagePaintType seems to do the right thing - // but maybe its treatment of anti-aliasing is incorrect. The kNoImage type - // controls drop shadow painting under transforms. It's not clear if we - // should behave like an opaque image here. + // but maybe its treatment of anti-aliasing is incorrect. The kNonOpaqueImage + // type controls drop shadow painting under transforms. It's not clear if we + // should behave like a non-opaque image here, but the element may not be + // opaque so going with that for now. Draw<OverdrawOp::kNone>( [paint_record, x, y, dwidth, dheight, box_rect]( cc::PaintCanvas* c, const cc::PaintFlags* flags) { @@ -845,7 +846,7 @@ [](const SkIRect& rect) { return false; }, // overdraw test lambda gfx::RectF(box_rect.width(), box_rect.height()), CanvasRenderingContext2DState::kImagePaintType, - CanvasRenderingContext2DState::kNoImage, + CanvasRenderingContext2DState::kNonOpaqueImage, CanvasPerformanceMonitor::DrawType::kElement); }
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.cc b/third_party/blink/renderer/platform/bindings/callback_function_base.cc index 1639afc..28f8aebd 100644 --- a/third_party/blink/renderer/platform/bindings/callback_function_base.cc +++ b/third_party/blink/renderer/platform/bindings/callback_function_base.cc
@@ -105,7 +105,7 @@ void CallbackFunctionWithTaskAttributionBase::Trace(Visitor* visitor) const { CallbackFunctionBase::Trace(visitor); - visitor->Trace(parent_task_); + visitor->Trace(task_state_); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/bindings/callback_function_base.h b/third_party/blink/renderer/platform/bindings/callback_function_base.h index 9748a5d17..2446bfd6e 100644 --- a/third_party/blink/renderer/platform/bindings/callback_function_base.h +++ b/third_party/blink/renderer/platform/bindings/callback_function_base.h
@@ -128,12 +128,12 @@ public: ~CallbackFunctionWithTaskAttributionBase() override = default; - scheduler::TaskAttributionInfo* GetParentTask() const { - return parent_task_.Get(); + scheduler::TaskAttributionInfo* GetTaskState() const { + return task_state_.Get(); } - void SetParentTask(scheduler::TaskAttributionInfo* task) { - parent_task_ = task; + void SetTaskState(scheduler::TaskAttributionInfo* task) { + task_state_ = task; } void Trace(Visitor* visitor) const override; @@ -143,7 +143,7 @@ : CallbackFunctionBase(object) {} private: - Member<scheduler::TaskAttributionInfo> parent_task_; + Member<scheduler::TaskAttributionInfo> task_state_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h b/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h index eff5c43da..324ab0a2 100644 --- a/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h +++ b/third_party/blink/renderer/platform/scheduler/public/task_attribution_tracker.h
@@ -170,7 +170,7 @@ TaskAttributionInfo* task_state) = 0; // Get the `TaskAttributionInfo` for the currently running task. - virtual TaskAttributionInfo* RunningTask() const = 0; + virtual TaskAttributionInfo* CurrentTaskState() const = 0; // Registers an observer to be notified when a `TaskScope` has been created. // Multiple `Observer`s can be registered, but only the innermost one will
diff --git a/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc b/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc index 2806ae1..9adff4f 100644 --- a/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc +++ b/third_party/blink/renderer/platform/widget/input/scroll_predictor_unittest.cc
@@ -194,17 +194,14 @@ EXPECT_EQ(expected_type, scroll_predictor_->filter_->GetName()); } - void InitLinearResamplingTest(bool use_frames_based_experimental_prediction) { + void InitLinearResamplingTest() { base::FieldTrialParams predictor_params; predictor_params["predictor"] = ::features::kPredictorNameLinearResampling; base::test::FeatureRefAndParams prediction_params = { features::kResamplingScrollEvents, predictor_params}; base::FieldTrialParams prediction_type_params; - prediction_type_params["mode"] = - use_frames_based_experimental_prediction - ? ::features::kPredictionTypeFramesBased - : ::features::kPredictionTypeTimeBased; + prediction_type_params["mode"] = ::features::kPredictionTypeFramesBased; base::test::FeatureRefAndParams experimental_prediction_params = { ::features::kResamplingScrollEventsExperimentalPrediction, prediction_type_params}; @@ -433,38 +430,13 @@ } TEST_F(ScrollPredictorTest, LinearResamplingPredictorTest) { - // Test kResamplingScrollEventsExperimentalLatencyFixed - InitLinearResamplingTest(false); + // Test kResamplingScrollEventsExperimentalLatencyVariable + InitLinearResamplingTest(); SendGestureScrollBegin(); // Send 1st GSU, no prediction available. std::unique_ptr<WebInputEvent> gesture_update = CreateGestureScrollUpdate(0, 10, 10 /* ms */); - HandleResampleScrollEvents(gesture_update, 10 /* ms */, 30 /* Hz */); - EXPECT_EQ(10, static_cast<const WebGestureEvent*>(gesture_update.get()) - ->data.scroll_update.delta_y); - EXPECT_EQ( - WebInputEvent::GetStaticTimeStampForTests() + - base::Milliseconds(10 /* ms */), - static_cast<const WebGestureEvent*>(gesture_update.get())->TimeStamp()); - - // Prediction using fixed +3.3ms latency. - gesture_update = CreateGestureScrollUpdate(0, 10, 20 /* ms */); - HandleResampleScrollEvents(gesture_update, 20 /* ms */, 30 /* Hz */); - ASSERT_FLOAT_EQ(10 + 3.3, - static_cast<const WebGestureEvent*>(gesture_update.get()) - ->data.scroll_update.delta_y); - EXPECT_EQ( - WebInputEvent::GetStaticTimeStampForTests() + - base::Milliseconds(23.3 /* ms */), - static_cast<const WebGestureEvent*>(gesture_update.get())->TimeStamp()); - - // Test kResamplingScrollEventsExperimentalLatencyVariable - InitLinearResamplingTest(true); - SendGestureScrollBegin(); - - // Send 1st GSU, no prediction available. - gesture_update = CreateGestureScrollUpdate(0, 10, 10 /* ms */); HandleResampleScrollEvents(gesture_update, 10 /* ms */, 60 /* Hz */); EXPECT_EQ(10, static_cast<const WebGestureEvent*>(gesture_update.get()) ->data.scroll_update.delta_y); @@ -605,37 +577,5 @@ EXPECT_NEAR(accumulated_deltas[i], GetLastAccumulatedDelta().y(), 0.00001); } } - -TEST_F(ScrollPredictorTest, HandleScrollPredictorFailure) { - ConfigureFilterFieldTrialAndInitialize(features::kFilteringScrollPrediction, - ""); - InitLinearResamplingTest(false); - SendGestureScrollBegin(); - - std::unique_ptr<WebInputEvent> gesture_update = - CreateGestureScrollUpdate(0, 5, 3 /* ms */); - HandleResampleScrollEvents(gesture_update, 4 /* ms */, 120 /* Hz */); - - gesture_update = CreateGestureScrollUpdate(0, 10, 6 /* ms */); - HandleResampleScrollEvents(gesture_update, 7 /* ms */, 120 /* Hz */); - - gesture_update = CreateGestureScrollUpdate(0, 15, 9 /* ms */); - HandleResampleScrollEvents(gesture_update, 10 /* ms */, 120 /* Hz */); - - float last_accumulated_delta_before_failure = GetLastAccumulatedDelta().y(); - // Prediction will fail in here because current event delta is 1ms. - // The minimum event delta of linear resampling predictor is 2ms. - // kResampleMinDelta in src/ui/base/prediction/linear_resampling.cc - gesture_update = CreateGestureScrollUpdate(0, 20, 10 /* ms */); - HandleResampleScrollEvents(gesture_update, 11 /* ms */, 120 /* Hz */); - float last_accumulated_delta_after_failure = GetLastAccumulatedDelta().y(); - - EXPECT_EQ(20, static_cast<const WebGestureEvent*>(gesture_update.get()) - ->data.scroll_update.delta_y); - EXPECT_NEAR(last_accumulated_delta_after_failure, - last_accumulated_delta_before_failure + 20 /* original delta */, - kEpsilon); -} - } // namespace test } // namespace blink
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 90b3e64..1aedffe 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -1054,6 +1054,13 @@ ], }, { + 'paths': + ['third_party/blink/public/common/messaging/transferable_message.h'], + 'allowed': [ + 'scheduler::TaskAttributionId', + ], + }, + { 'paths': [ 'third_party/blink/renderer/core/exported', 'third_party/blink/renderer/core/frame',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 6dd8f9c..29c187c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6329,12 +6329,6 @@ crbug.com/366415131 external/wpt/html/semantics/forms/the-select-element/customizable-select/picker-and-slotted.tentative.html [ Failure ] ### Tests failing with CSSGapDecorations Enabled: -crbug.com/357648037 virtual/css-gap-decorations/animations/interpolation/webkit-column-rule-color-interpolation.html [ Crash Failure Timeout ] -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/css/css-animations/responsive/column-rule-color-001.html [ Failure ] -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/css/css-multicol/animation/column-rule-color-interpolation.html [ Failure ] -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001.html [ Crash Failure Timeout ] -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/web-animations/animation-model/animation-types/addition-per-property-001.html [ Crash Failure Timeout ] -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001.html [ Crash Failure Timeout ] # These tests failing for interpolation and animations, which we haven't worked on for GapDecorations yet: crbug.com/419066541 animations/interpolation/webkit-column-rule-color-interpolation.html [ Failure ] crbug.com/419066541 animations/interpolation/webkit-column-rule-width-interpolation.html [ Failure ] @@ -6343,11 +6337,16 @@ crbug.com/419066541 external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001.html [ Failure ] crbug.com/419066541 external/wpt/web-animations/animation-model/animation-types/addition-per-property-001.html [ Failure ] crbug.com/419066541 external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001.html [ Failure ] -# These tests are failing due to wrong expectations file, must update the expectations file: -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/css/css-multicol/column-height-009.html [ Failure ] -# These tests are failing due to not handling OOF in multicol, will be addressed in follow up CL. -crbug.com/357648037 virtual/css-gap-decorations/external/wpt/css/css-multicol/multicol-nested-column-rule-002.html [ Failure ] ### End of tests failing with CSSGapDecorations Enabled +### Tests for CSSGapDecorations disabled +crbug.com/419066541 virtual/css-gap-decorations-disabled/animations/interpolation/webkit-column-rule-color-interpolation.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/animations/interpolation/webkit-column-rule-width-interpolation.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/external/wpt/css/css-animations/responsive/column-rule-color-001.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/external/wpt/css/css-multicol/animation/column-rule-color-interpolation.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/addition-per-property-001.html [ Pass ] +crbug.com/419066541 virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001.html [ Pass ] +### End Of tests for CSSGapDecorations disabled # I think these are just test issues, but at least the scrollbars are related: crbug.com/362536387 external/wpt/html/semantics/forms/the-select-element/select-many-options.tentative.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestLists/content_shell.filter b/third_party/blink/web_tests/TestLists/content_shell.filter index 1914f62d..2bfd298 100644 --- a/third_party/blink/web_tests/TestLists/content_shell.filter +++ b/third_party/blink/web_tests/TestLists/content_shell.filter
@@ -898,7 +898,6 @@ virtual/backface-visibility-interop/external/wpt/css/css-transforms/ttwf-css-3d-polygon-cycle.html virtual/composite-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-animation* virtual/composite-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-transition* -virtual/css-gap-decorations/external/wpt/css/css-ui/compute-kind-widget-no-fallback-props-001.html virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/reset-algorithm-rendering.html virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/select-tabindex-order.tentative.html virtual/dark-color-scheme/external/wpt/css/css-color/system-color-consistency.html
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 52edcdb..74dd197 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -408,34 +408,19 @@ ] }, { - "prefix": "css-gap-decorations", - "exclusive_tests": [ - "external/wpt/css/css-gaps" - ], - "platforms": [ - "Linux" - ], + "prefix": "css-gap-decorations-disabled", + "platforms": ["Linux"], "bases": [ - "external/wpt/css/css-multicol", - "external/wpt/web-animations/animation-model/animation-types", "animations/interpolation/webkit-column-rule-color-interpolation.html", - "fast/multicol", - "external/wpt/web-animations/responsive/to-color-change.html", - "external/wpt/css/css-typed-om/the-stylepropertymap/properties/column-rule-color.html", + "animations/interpolation/webkit-column-rule-width-interpolation.html", + "external/wpt/css/css-multicol/animation/column-rule-color-interpolation.html", "external/wpt/css/css-animations/responsive/column-rule-color-001.html", - "external/wpt/css/css-cascade/all-prop-revert-layer.html", - "external/wpt/css/css-ui/compute-kind-widget-no-fallback-props-001.html", - "external/wpt/css/cssom/declaration-block-all-crash.html", - "external/wpt/css/css-gaps" - ], - "args": [ - "--enable-blink-features=CSSGapDecoration" - ], - "expires": "Oct 1, 2025", - "owners": [ - "samomekarajr@microsoft.com", - "almaher@microsoft.com" - ] + "external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001.html", + "external/wpt/web-animations/animation-model/animation-types/addition-per-property-001.html", + "external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001.html"], + "args": ["--disable-blink-features=CSSGapDecoration"], + "expires": "June 1, 2026", + "owners": ["samomekarajr@microsoft.com", "almaher@microsoft.com", "javiercon@microsoft.com"] }, { "prefix": "css-line-clamp-line-breaking-ellipsis", @@ -2339,6 +2324,27 @@ ] }, { + "prefix": "overscroll-behavior-all-scroll-containers", + "platforms": [ + "Linux", + "Mac", + "Win" + ], + "bases": [ + "external/wpt/css/css-overscroll-behavior/overscroll-behavior-without-overflow.html", + "fast/scroll-behavior/overscroll-behavior.html" + ], + "exclusive_tests": "ALL", + "args": [ + "--enable-features=OverscrollBehaviorRespectedOnAllScrollContainers" + ], + "owners": [ + "perryuwang@gmail.com", + "flackr@chromium.org" + ], + "expires": "Jan 1, 2026" + }, + { "prefix": "parakeet", "owners": [ "brandm@microsoft.com"
diff --git a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js index ae21b463..f520646 100644 --- a/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/language_detection/detector.https.window.js
@@ -27,7 +27,7 @@ promise_test(async t => { const detector = await createLanguageDetector(); - const results = await detector.detect('Hello world!'); + const results = await detector.detect(kTestPrompt); // must at least have the 'und' result. assert_greater_than_equal(results.length, 1); @@ -89,35 +89,17 @@ }, 'Aborting createLanguageDetector().'); promise_test(async t => { - const detector = await createLanguageDetector(); - - const text = 'Hello world!'; - const promises = [detector.detect(text), detector.measureInputUsage(text)]; - - detector.destroy(); - - promises.push(detector.detect(text), detector.measureInputUsage(text)); - - for (const promise of promises) { - await promise_rejects_dom(t, 'AbortError', promise); - } + await testDestroy(t, createLanguageDetector, {}, [ + detector => detector.detect(kTestPrompt), + detector => detector.measureInputUsage(kTestPrompt), + ]); }, 'Calling LanguageDetector.destroy() aborts calls to detect and measureInputUsage.'); promise_test(async t => { - const controller = new AbortController(); - const detector = await createLanguageDetector({signal: controller.signal}); - - const text = 'Hello world!'; - const promises = [detector.detect(text), detector.measureInputUsage(text)]; - - const error = new Error('The create abort signal was aborted.'); - controller.abort(error); - - promises.push(detector.detect(text), detector.measureInputUsage(text)); - - for (const promise of promises) { - await promise_rejects_exactly(t, error, promise); - } + await testCreateAbort(t, createLanguageDetector, {}, [ + detector => detector.detect(kTestPrompt), + detector => detector.measureInputUsage(kTestPrompt), + ]); }, 'LanguageDetector.create()\'s abort signal destroys its LanguageDetector after creation.'); promise_test(async t => { @@ -126,7 +108,7 @@ const detector = await createLanguageDetector(); const detectPromise = - detector.detect('Hello world!', {signal: controller.signal}); + detector.detect(kTestPrompt, { signal: controller.signal }); await promise_rejects_dom(t, 'AbortError', detectPromise); }, 'LanguageDetector.detect() call with an aborted signal.'); @@ -134,7 +116,7 @@ promise_test(async t => { const detector = await createLanguageDetector(); await testAbortPromise(t, signal => { - return detector.detect('Hello world!', {signal}); + return detector.detect(kTestPrompt, { signal }); }); }, 'Aborting LanguageDetector.detect().'); @@ -163,7 +145,7 @@ const detector = await createLanguageDetector(); const measureInputUsagePromise = - detector.measureInputUsage('hello', {signal: controller.signal}); + detector.measureInputUsage(kTestPrompt, { signal: controller.signal }); await promise_rejects_dom(t, 'AbortError', measureInputUsagePromise); }, 'LanguageDetector.measureInputUsage() call with an aborted signal.'); @@ -171,7 +153,7 @@ promise_test(async t => { const detector = await createLanguageDetector(); await testAbortPromise(t, signal => { - return detector.measureInputUsage('hello', {signal}); + return detector.measureInputUsage(kTestPrompt, { signal }); }); }, 'Aborting LanguageDetector.measureInputUsage().');
diff --git a/third_party/blink/web_tests/external/wpt/ai/resources/util.js b/third_party/blink/web_tests/external/wpt/ai/resources/util.js index eda6a17..8f9efad 100644 --- a/third_party/blink/web_tests/external/wpt/ai/resources/util.js +++ b/third_party/blink/web_tests/external/wpt/ai/resources/util.js
@@ -239,3 +239,33 @@ await test_driver.bless(); return await Rewriter.create(options); } + +async function testDestroy(t, createMethod, options, instanceMethods) { + const instance = await createMethod(options); + + const promises = instanceMethods.map(method => method(instance)); + + instance.destroy(); + + promises.push(...instanceMethods.map(method => method(instance))); + + for (const promise of promises) { + await promise_rejects_dom(t, 'AbortError', promise); + } +} + +async function testCreateAbort(t, createMethod, options, instanceMethods) { + const controller = new AbortController(); + const instance = await createMethod({...options, signal: controller.signal}); + + const promises = instanceMethods.map(method => method(instance)); + + const error = new Error('The create abort signal was aborted.'); + controller.abort(error); + + promises.push(...instanceMethods.map(method => method(instance))); + + for (const promise of promises) { + await promise_rejects_exactly(t, error, promise); + } +}
diff --git a/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js index d275ba5..59c7da3 100644 --- a/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite-streaming.tentative.https.window.js
@@ -21,9 +21,12 @@ promise_test(async (t) => { const rewriter = await createRewriter(); + const stream = rewriter.rewriteStreaming(kTestPrompt); + rewriter.destroy(); - assert_throws_dom( - 'InvalidStateError', () => rewriter.rewriteStreaming(kTestPrompt)); + + await promise_rejects_dom( + t, 'AbortError', stream.pipeTo(new WritableStream())); }, 'Rewriter.rewriteStreaming() fails after destroyed'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite.tentative.https.window.js index 07e8b41..55ec52b 100644 --- a/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/rewriter/rewriter-rewrite.tentative.https.window.js
@@ -19,25 +19,32 @@ promise_test(async (t) => { const rewriter = await createRewriter(); - const result = await rewriter.rewrite(kTestPrompt, { context: ' ' }); + const result = await rewriter.rewrite(kTestPrompt, {context: ' '}); assert_not_equals(result, ''); }, 'Rewriter.rewrite() with a whitespace context returns a non-empty result'); -promise_test(async (t) => { - const rewriter = await createRewriter(); - rewriter.destroy(); - await promise_rejects_dom( - t, 'InvalidStateError', rewriter.rewrite(kTestPrompt)); -}, 'Rewriter.rewrite() fails after destroyed'); +promise_test(async t => { + await testDestroy(t, createRewriter, {}, [ + rewriter => rewriter.rewrite(kTestPrompt), + rewriter => rewriter.measureInputUsage(kTestPrompt), + ]); +}, 'Calling Rewriter.destroy() aborts calls to rewrite and measureInputUsage.'); + +promise_test(async t => { + await testCreateAbort(t, createRewriter, {}, [ + rewriter => rewriter.rewrite(kTestPrompt), + rewriter => rewriter.measureInputUsage(kTestPrompt), + ]); +}, 'Rewriter.create()\'s abort signal destroys its Rewriter after creation.'); promise_test(async () => { const rewriter = await createRewriter(); - const result = await rewriter.rewrite(kTestPrompt, { context: kTestContext }); + const result = await rewriter.rewrite(kTestPrompt, {context: kTestContext}); assert_equals(typeof result, 'string'); }, 'Simple Rewriter.rewrite() call'); promise_test(async () => { const rewriter = await createRewriter(); await Promise.all( - [rewriter.rewrite(kTestPrompt), rewriter.rewrite(kTestPrompt)]); + [rewriter.rewrite(kTestPrompt), rewriter.rewrite(kTestPrompt)]); }, 'Multiple Rewriter.rewrite() calls are resolved successfully');
diff --git a/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize-streaming.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize-streaming.tentative.https.window.js index 09a8fb0d..2a41369 100644 --- a/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize-streaming.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize-streaming.tentative.https.window.js
@@ -21,8 +21,12 @@ promise_test(async (t) => { const summarizer = await createSummarizer(); + const stream = summarizer.summarizeStreaming(kTestPrompt); + summarizer.destroy(); - assert_throws_dom('InvalidStateError', () => summarizer.summarizeStreaming(kTestPrompt)); + + await promise_rejects_dom( + t, 'AbortError', stream.pipeTo(new WritableStream())); }, 'Summarizer.summarizeStreaming() fails after destroyed'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize.tentative.https.window.js index a9be36d..8753a48 100644 --- a/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/summarizer/summarizer-summarize.tentative.https.window.js
@@ -15,15 +15,23 @@ promise_test(async (t) => { const summarizer = await createSummarizer(); - const result = await summarizer.summarize(kTestPrompt, { context: ' ' }); + const result = await summarizer.summarize(kTestPrompt, {context: ' '}); assert_not_equals(result, ''); }, 'Summarizer.summarize() with a whitespace context returns an empty result'); -promise_test(async (t) => { - const summarizer = await createSummarizer(); - summarizer.destroy(); - await promise_rejects_dom(t, 'InvalidStateError', summarizer.summarize(kTestPrompt)); -}, 'Summarizer.summarize() fails after destroyed'); +promise_test(async t => { + await testDestroy(t, createSummarizer, {}, [ + summarizer => summarizer.summarize(kTestPrompt), + summarizer => summarizer.measureInputUsage(kTestPrompt), + ]); +}, 'Calling Summarizer.destroy() aborts calls to summarize and measureInputUsage.'); + +promise_test(async t => { + await testCreateAbort(t, createSummarizer, {}, [ + summarizer => summarizer.summarize(kTestPrompt), + summarizer => summarizer.measureInputUsage(kTestPrompt), + ]); +}, 'Summarizer.create()\'s abort signal destroys its Summarizer after creation.'); promise_test(async () => { const summarizer = await createSummarizer(); @@ -34,8 +42,6 @@ promise_test(async () => { const summarizer = await createSummarizer(); - await Promise.all([ - summarizer.summarize(kTestPrompt), - summarizer.summarize(kTestPrompt) - ]); + await Promise.all( + [summarizer.summarize(kTestPrompt), summarizer.summarize(kTestPrompt)]); }, 'Multiple Summarizer.summarize() calls are resolved successfully');
diff --git a/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js b/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js index 94be911..1b2519cf2 100644 --- a/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js
@@ -109,42 +109,32 @@ }, 'Aborting Translator.translate().'); promise_test(async t => { - const translator = - await createTranslator({sourceLanguage: 'en', targetLanguage: 'ja'}); + await testDestroy( + t, createTranslator, { sourceLanguage: 'en', targetLanguage: 'ja' }, [ + translator => translator.translate(kTestPrompt), + translator => translator.measureInputUsage(kTestPrompt), + ]); +}, 'Calling Translator.destroy() aborts calls to write and measureInputUsage.'); - const text = 'this string is in English'; - const promises = - [translator.translate(text), translator.measureInputUsage(text)]; +promise_test(async (t) => { + const translator = + await createTranslator({ sourceLanguage: 'en', targetLanguage: 'ja' }); + const stream = translator.translateStreaming(kTestPrompt); translator.destroy(); - promises.push(translator.translate(text), translator.measureInputUsage(text)); - - for (const promise of promises) { - await promise_rejects_dom(t, 'AbortError', promise); - } -}, 'Calling Translator.destroy() aborts calls to translate and measureInputUsage.'); + await promise_rejects_dom( + t, 'AbortError', stream.pipeTo(new WritableStream())); +}, 'Translator.translateStreaming() fails after destroyed'); promise_test(async t => { - const controller = new AbortController(); - const translator = await createTranslator( - {sourceLanguage: 'en', targetLanguage: 'ja', signal: controller.signal}); - - const text = 'this string is in English'; - const promises = - [translator.translate(text), translator.measureInputUsage(text)]; - - const error = new Error('The create abort signal was aborted.'); - controller.abort(error); - - promises.push(translator.translate(text), translator.measureInputUsage(text)); - - for (const promise of promises) { - await promise_rejects_exactly(t, error, promise); - } + await testCreateAbort( + t, createTranslator, { sourceLanguage: 'en', targetLanguage: 'ja' }, [ + translator => translator.translate(kTestPrompt), + translator => translator.measureInputUsage(kTestPrompt), + ]); }, 'Translator.create()\'s abort signal destroys its Translator after creation.'); - promise_test(async t => { await testMonitor( createTranslator, {sourceLanguage: 'en', targetLanguage: 'ja'});
diff --git a/third_party/blink/web_tests/external/wpt/ai/writer/writer-write-streaming.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/writer/writer-write-streaming.tentative.https.window.js index 67286a7..122acb0 100644 --- a/third_party/blink/web_tests/external/wpt/ai/writer/writer-write-streaming.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/writer/writer-write-streaming.tentative.https.window.js
@@ -21,8 +21,12 @@ promise_test(async (t) => { const writer = await createWriter(); + const stream = writer.writeStreaming(kTestPrompt); + writer.destroy(); - assert_throws_dom('InvalidStateError', () => writer.writeStreaming(kTestPrompt)); + + await promise_rejects_dom( + t, 'AbortError', stream.pipeTo(new WritableStream())); }, 'Writer.writeStreaming() fails after destroyed'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/ai/writer/writer-write.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/writer/writer-write.tentative.https.window.js index 3383ceb..a49f04e 100644 --- a/third_party/blink/web_tests/external/wpt/ai/writer/writer-write.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/writer/writer-write.tentative.https.window.js
@@ -19,15 +19,23 @@ promise_test(async (t) => { const writer = await createWriter(); - const result = await writer.write(kTestPrompt, { context: ' ' }); + const result = await writer.write(kTestPrompt, {context: ' '}); assert_not_equals(result, ''); }, 'Writer.write() with a whitespace context returns a non-empty result'); -promise_test(async (t) => { - const writer = await createWriter(); - writer.destroy(); - await promise_rejects_dom(t, 'InvalidStateError', writer.write(kTestPrompt)); -}, 'Writer.write() fails after destroyed'); +promise_test(async t => { + await testDestroy(t, createWriter, {}, [ + writer => writer.write(kTestPrompt), + writer => writer.measureInputUsage(kTestPrompt), + ]); +}, 'Calling Writer.destroy() aborts calls to write and measureInputUsage.'); + +promise_test(async t => { + await testCreateAbort(t, createWriter, {}, [ + writer => writer.write(kTestPrompt), + writer => writer.measureInputUsage(kTestPrompt), + ]); +}, 'Writer.create()\'s abort signal destroys its Writer after creation.'); promise_test(async () => { const writer = await createWriter();
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012-ref.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012-ref.html new file mode 100644 index 0000000..3f63ce1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012-ref.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Overflow Ref: scroll-target-group property with viewport scroller</title> +<style> + #wrapper { + position: fixed; + } + + #scroller { + overflow: auto; + height: 130px; + width: 100px; + } + + .item { + width: 100px; + height: 300px; + background-color: blue; + margin: 5px; + } + + a { + color: red; + } + + #targetCurrent { + color: green; + } +</style> +<div id="wrapper"> + <a href="#target1">t1</a> + <a id="targetCurrent" href="#target2">t2</a> + <a href="#target3">t3</a> + <a href="#target4">t4</a> +</div> +<div class="item" id="target1"></div> +<div class="item" id="target2"></div> +<div class="item" id="target3"></div> +<div class="item" id="target4"></div> +<script> + document.documentElement.scrollTop = 250; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012.html new file mode 100644 index 0000000..f8f8a07a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-target-group-012.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Overflow Test: scroll-target-group property with viewport scroller</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-target-group"> +<link rel="match" href="scroll-target-group-012-ref.html"> +<style> + #wrapper { + scroll-target-group: auto; + position: fixed; + } + + #scroller { + overflow: auto; + height: 130px; + width: 100px; + } + + .item { + width: 100px; + height: 300px; + background-color: blue; + margin: 5px; + } + + a { + color: red; + } + + a:target-current { + color: green; + } +</style> +<div id="wrapper"> + <a href="#target1">t1</a> + <a href="#target2">t2</a> + <a href="#target3">t3</a> + <a href="#target4">t4</a> +</div> +<div class="item" id="target1"></div> +<div class="item" id="target2"></div> +<div class="item" id="target3"></div> +<div class="item" id="target4"></div> +<script> + document.documentElement.scrollTop = 250; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscroll-behavior-without-overflow.html b/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscroll-behavior-without-overflow.html new file mode 100644 index 0000000..1491ff6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overscroll-behavior/overscroll-behavior-without-overflow.html
@@ -0,0 +1,133 @@ +<!doctype html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/dom/events/scrolling/scroll_support.js"></script> +<script src="/css/css-scroll-snap/support/common.js"></script> +<link rel="help" href="https://drafts.csswg.org/css-overscroll-behavior"> + +<style> +body { + margin: 0; + width: 150vw; + height: 150vh; +} +#container { + width: 500px; + height: 300px; + border: 2px solid orange; + border-radius: 5px; + overflow: scroll; +} +#content { + background: repeating-linear-gradient(to bottom right, blue 15%, white 30%); + width: 400px; + height: 200px; +} +</style> + +<body> + <div id="container"> + <div id="content"></div> + </div> +</body> + +<script> +const container = document.getElementById('container'); +const content = document.getElementById('content'); +const scrollAmount = 120; +const scrollRight = { dx: scrollAmount, dy: 0 }; +const scrollDown = { dx: 0, dy: scrollAmount }; +const startPosition = { x: 200, y: 100 }; + +async function performGestureScroll(posX, posY, deltaX, deltaY) { + await new test_driver.Actions() + .scroll(posX, posY, deltaX, deltaY) + .send(); + await waitForCompositorCommit(); +} + +promise_test(async (t) => { + window.scrollTo(0, 0); + container.style.overflow = 'hidden'; + container.style.overscrollBehaviorX = 'none'; + container.style.overscrollBehaviorY = 'auto'; + await waitForCompositorCommit(); + + assert_equals(window.scrollX, 0); + assert_equals(window.scrollY, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollRight.dx, scrollRight.dy); + assert_equals(window.scrollX, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollDown.dx, scrollDown.dy); + assert_greater_than(window.scrollY, 100); +}, 'overflow: hidden and overscroll-behavior-x: none should only prevent ' + + 'scroll propagation on x axis.'); + +promise_test(async (t) => { + window.scrollTo(0, 0); + container.style.overflow = 'hidden'; + container.style.overscrollBehaviorX = 'auto'; + container.style.overscrollBehaviorY = 'none'; + await waitForCompositorCommit(); + + assert_equals(window.scrollX, 0); + assert_equals(window.scrollY, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollRight.dx, scrollRight.dy); + assert_greater_than(window.scrollX, 100); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollDown.dx, scrollDown.dy); + assert_equals(window.scrollY, 0); +}, 'overflow: hidden and overscroll-behavior-y: none should only prevent ' + + 'scroll propagation on y axis.'); + +promise_test(async (t) => { + window.scrollTo(0, 0); + container.style.overflow = 'auto'; + container.style.overscrollBehaviorX = 'none'; + container.style.overscrollBehaviorY = 'auto'; + await waitForCompositorCommit(); + + assert_equals(window.scrollX, 0); + assert_equals(window.scrollY, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollRight.dx, scrollRight.dy); + assert_equals(window.scrollX, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, scrollDown.dx, scrollDown.dy); + assert_greater_than(window.scrollY, 100); +}, 'overflow: auto and overscroll-behavior-x: none should only prevent ' + + 'scroll propagation on x axis.'); + +promise_test(async (t) => { + window.scrollTo(0, 0); + container.style.overflow = 'auto'; + container.style.overscrollBehaviorX = 'auto'; + container.style.overscrollBehaviorY = 'none'; + await waitForCompositorCommit(); + + assert_equals(window.scrollX, 0); + assert_equals(window.scrollY, 0); + + await performGestureScroll( + startPosition.x, startPosition.y, + scrollRight.dx, scrollRight.dy); + assert_greater_than(window.scrollX, 100); + + await performGestureScroll( + startPosition.x, startPosition.y, + scrollDown.dx, scrollDown.dy); + assert_equals(window.scrollY, 0); +}, 'overflow: auto and overscroll-behavior-y: none should only prevent ' + + 'scroll propagation on y axis.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/debug-header.https.html b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/debug-header.https.html index 631151bc..4f384bf 100644 --- a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/debug-header.https.html +++ b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/debug-header.https.html
@@ -7,7 +7,7 @@ <script src="helper.js" type="module"></script> <script type="module"> - import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState } from "./helper.js"; + import { expireCookie, documentHasCookie, waitForCookie, addCookieAndSessionCleanup, configureServer, setupShardedServerState, postJson } from "./helper.js"; promise_test(async t => { await setupShardedServerState(); @@ -76,4 +76,40 @@ const headers = new Headers(await response.json()); assert_equals(headers.get("secure-session-skipped"), null); }, "Cross-site redirects do not send debug header"); + + promise_test(async t => { + await setupShardedServerState(); + const expectedCookieAndValue1 = "auth_cookie=abcdef0123"; + const expectedCookieAndAttributes1 = `${expectedCookieAndValue1};Domain=${location.hostname};Path=/device-bound-session-credentials`; + const expectedCookieAndValue2 = "other_cookie=ghijkl4567"; + const expectedCookieAndAttributes2 = `${expectedCookieAndValue2};Domain=${location.hostname};Path=/device-bound-session-credentials`; + addCookieAndSessionCleanup(t); + + // Configure server to configure cookies for next two created sessions. + configureServer({ + cookieDetailsForNextRegisteredSessions: [[{ nameAndValue: expectedCookieAndValue1 }], [{ nameAndValue: expectedCookieAndValue2 }]] + }); + + // Prompt starting one session, and wait until registration completes. + const loginResponse = await postJson('login.py', { numSessions: 2 }); + assert_equals(loginResponse.status, 200); + await waitForCookie(expectedCookieAndValue1, /*expectCookie=*/true); + await waitForCookie(expectedCookieAndValue2, /*expectCookie=*/true); + + // Configure server to fail to refresh + configureServer({ refreshEndpointUnavailable: true }); + + // Expire the cookie. The server will attempt a refresh, but fail. + expireCookie(expectedCookieAndAttributes1); + expireCookie(expectedCookieAndAttributes2); + assert_false(documentHasCookie(expectedCookieAndValue1)); + assert_false(documentHasCookie(expectedCookieAndValue2)); + + const response = await fetch('reflect_headers.py'); + assert_equals(response.status, 200); + assert_false(documentHasCookie(expectedCookieAndValue1)); + assert_false(documentHasCookie(expectedCookieAndValue2)); + const headers = new Headers(await response.json()); + assert_equals(headers.get("secure-session-skipped"), "server_error;session_identifier=\"0\", server_error;session_identifier=\"1\""); + }, "Two failing sessions both set debug header"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/multiple-registrations.https.html b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/multiple-registrations.https.html index d5563eb..ef024bd 100644 --- a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/multiple-registrations.https.html +++ b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/multiple-registrations.https.html
@@ -12,10 +12,9 @@ await setupShardedServerState(); const expectedCookieAndValue1 = "auth_cookie=abcdef0123"; const expectedCookieAndAttributes1 = `${expectedCookieAndValue1};Domain=${location.hostname};Path=/device-bound-session-credentials`; - addCookieAndSessionCleanup(t, expectedCookieAndAttributes1); const expectedCookieAndValue2 = "other_cookie=ghijkl4567"; const expectedCookieAndAttributes2 = `${expectedCookieAndValue2};Domain=${location.hostname};Path=/device-bound-session-credentials`; - addCookieAndSessionCleanup(t, expectedCookieAndAttributes2); + addCookieAndSessionCleanup(t); // Configure server to configure cookies for next two created sessions. configureServer({
diff --git a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/resolving-urls.https.html b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/resolving-urls.https.html index e502eb4b..79f1594 100644 --- a/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/resolving-urls.https.html +++ b/third_party/blink/web_tests/external/wpt/device-bound-session-credentials/resolving-urls.https.html
@@ -12,7 +12,7 @@ await setupShardedServerState(); const expectedCookieAndValue = "auth_cookie=abcdef0123"; const expectedCookieAndAttributes = `${expectedCookieAndValue};Domain=${location.hostname};Path=/device-bound-session-credentials`; - addCookieAndSessionCleanup(t, expectedCookieAndAttributes); + addCookieAndSessionCleanup(t); // Configure server to use the absolute URL for refresh instead of a relative URL. configureServer({ refreshUrl });
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-1.png b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-1.png new file mode 100644 index 0000000..44526f5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-1.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-2.png b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-2.png new file mode 100644 index 0000000..bb59d9dc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/resources/images/lcp-256x256-alt-2.png Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/smoke/tentative/image-src-change.html b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/smoke/tentative/image-src-change.html new file mode 100644 index 0000000..a9bb1dc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/soft-navigation-heuristics/smoke/tentative/image-src-change.html
@@ -0,0 +1,79 @@ +<!DOCTYPE html> +<meta charset="utf-8" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/soft-navigation-heuristics/resources/soft-navigation-test-helper.js"></script> + +<button id="navigateButton">Click here!</button> +<img id="testImage" height="256" width="256" src="/images/lcp-256x256.png" elementtiming="test-image"></img> + +<script> + async function waitForImageRender() { + let entries = await new Promise(resolve => { + new PerformanceObserver((list, observer) => { + resolve(list.getEntries()); + observer.disconnect(); + }).observe({type: 'element', buffered: true}); + }); + assert_equals( + entries.length, 1, 'Expected exactly one ElementTiming entry'); + assert_equals( + entries[0].identifier, 'test-image', 'Unexpected ElementTiming entry.'); + } + + async function runTest(t, url, newImageSrc) { + navigateButton.addEventListener("click", () => { + history.pushState({}, '', url); + testImage.src = newImageSrc; + }, {once: true}); + + const softNavPromise = SoftNavigationTestHelper.getPerformanceEntries( + /*type=*/ "soft-navigation", + /*include_soft_navigation_observations=*/ false, + /*min_num_entries=*/ 1, + ); + + if (test_driver) { + test_driver.click(navigateButton); + } + + const helper = new SoftNavigationTestHelper(t); + const entries = await helper.withTimeoutMessage( + softNavPromise, "Soft navigation entry never arrived.", 3000); + assert_equals(entries.length, 1, 'Expected exactly one soft navigation.'); + assert_true( + entries[0].name.endsWith(url), + 'Unexpected Soft Navigation URL.'); + } + + // Wait for the image to initially load and make its way through the image + // timing pipeline before changing its source. + promise_setup(waitForImageRender); + + promise_test(async t => { + const url = '/image-src-change-1'; + const src = 'soft-navigation-heuristics/resources/images/lcp-256x256-alt-1.png'; + return runTest(t, url, src); + }, 'Soft Navigation Detection supports HTMLImageElment.src'); + + promise_test(async t => { + const url = '/image-src-change-2'; + const src = 'soft-navigation-heuristics/resources/images/lcp-256x256-alt-2.png'; + return runTest(t, url, src); + }, 'Soft Navigation Detection supports a multiple soft navigations setting HTMLImageElment.src'); + + promise_test(async t => { + const url = '/image-src-change-3'; + // base64 encoded /images/lcp-16x16.png. + const src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAArElEQVR4AZTQgQaEQBCA4b9pturiHPcu9/4PdMCp2trJybKwbMVi8Jn9TcXHeAdegWFn2HgE+o0+4Ix2O+ba6Na28V53Oi+3NI2XWxo1Lej2+QOiRgw13KKF3UDaHTW1yXmJWNI0i5zrzieNm7WgU8nxjmEWCXKlJOn9+CHqdkUt3x1LkkYnibsvatwkeXdB40bJuwuaatX8gukmucZ9NS8paOpR8pKCRv97DgBllRV8uazI0wAAAABJRU5ErkJggg=='; + return runTest(t, url, src); + }, 'Soft Navigation Detection supports a setting HTMLImageElment.src to a data URI'); + + promise_test(async t => { + const url = '/image-src-change-1'; + const src = 'soft-navigation-heuristics/resources/images/lcp-256x256-alt-1.png'; + return runTest(t, url, src); + }, 'Soft Navigation Detection supports a setting HTMLImageElment.src to a previous value'); +</script>
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/overscroll-behavior.html b/third_party/blink/web_tests/fast/scroll-behavior/overscroll-behavior.html index 4003888..02f15a01 100644 --- a/third_party/blink/web_tests/fast/scroll-behavior/overscroll-behavior.html +++ b/third_party/blink/web_tests/fast/scroll-behavior/overscroll-behavior.html
@@ -145,9 +145,24 @@ assert_equals(container.scrollLeft, 0); } -async function test_boundary_on_nonscrollable_allows_propagation(scrollGesture) -{ +async function test_boundary_on_nonscrollable_prevents_x(scrollGesture) { non_scrollable.style.overscrollBehaviorX = 'none'; + non_scrollable.style.overscrollBehaviorY = 'auto'; + await waitForCompositorCommit; + await waitForScrollReset(document.scrollingElement); + + await scrollGesture(non_scrollable, startPositionBottom, scrollRight); + assert_equals(window.scrollX, 0); + + await raf(); + + await scrollGesture(non_scrollable, startPositionBottom, scrollDown, + document); + assert_greater_than(window.scrollY, 100); +} + +async function test_boundary_on_nonscrollable_prevents_y(scrollGesture) { + non_scrollable.style.overscrollBehaviorX = 'auto'; non_scrollable.style.overscrollBehaviorY = 'none'; await waitForCompositorCommit; await waitForScrollReset(document.scrollingElement); @@ -158,9 +173,8 @@ await raf(); - await scrollGesture(non_scrollable, startPositionBottom, scrollDown, - document); - assert_greater_than(window.scrollY, 100); + await scrollGesture(non_scrollable, startPositionBottom, scrollDown); + assert_equals(window.scrollY, 0); } promise_test(t => { @@ -176,9 +190,13 @@ }, 'overscroll-behavior should not affect scrolling inside the applied ' + 'container with: wheel.'); promise_test(t => { - return test_boundary_on_nonscrollable_allows_propagation(performWheelScroll); -}, 'overscroll-behavior on non-scrollable area should not affect scroll ' + - 'propagation with: wheel.'); + return test_boundary_on_nonscrollable_prevents_x(performWheelScroll); +}, 'overscroll-behavior-x: none on non-scrollable area should only prevent ' + + 'scroll propagation on x axis with: wheel.'); +promise_test(t => { + return test_boundary_on_nonscrollable_prevents_y(performWheelScroll); +}, 'overscroll-behavior-y: none on non-scrollable area should only prevent ' + + 'scroll propagation on y axis with: wheel.'); const IS_MAC = navigator.platform.indexOf('Mac') == 0; if (!IS_MAC) { @@ -191,9 +209,12 @@ }, 'overscroll-behavior-x: none should only prevent scroll propagation on ' + 'x axis with: touch.'); promise_test(t => { - return test_boundary_on_nonscrollable_allows_propagation( - performTouchDrag); - }, 'overscroll-behavior on non-scrollable area should not affect scroll ' + - 'propagation with: touch.'); + return test_boundary_on_nonscrollable_prevents_x(performTouchDrag); + }, 'overscroll-behavior-x: none on non-scrollable area should only ' + + 'prevent scroll propagation on x axis with: touch.'); + promise_test(t => { + return test_boundary_on_nonscrollable_prevents_y(performTouchDrag); + }, 'overscroll-behavior-y: none on non-scrollable area should only ' + + 'prevent scroll propagation on y axis with: touch.'); } </script>
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/README.md b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/README.md new file mode 100644 index 0000000..5e004c3 --- /dev/null +++ b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/README.md
@@ -0,0 +1,2 @@ +Testing tests that were disabled when CSSGapDecorations became "experimental", +to make sure we don't regress them without the flag on.
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001-expected.txt b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001-expected.txt new file mode 100644 index 0000000..830d194 --- /dev/null +++ b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-001-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +Found 5 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] columns: positive integer + assert_equals: The value should be 3 at 0ms expected "3" but got "auto 3" +[FAIL] columns: length + assert_equals: The value should be 20px at 0ms expected "20px" but got "20px auto" +[FAIL] columns: length of rem + assert_equals: The value should be 20px at 0ms expected "20px" but got "20px auto" +[FAIL] flex-flow: "row" onto "row-reverse wrap" + assert_equals: The value should be row at 0ms expected "row" but got "row nowrap" +[FAIL] font-style: "oblique" onto "italic" + assert_equals: The value should be oblique at 0ms expected "oblique" but got "italic" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/addition-per-property-001-expected.txt b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/addition-per-property-001-expected.txt new file mode 100644 index 0000000..830d194 --- /dev/null +++ b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/addition-per-property-001-expected.txt
@@ -0,0 +1,14 @@ +This is a testharness.js-based test. +Found 5 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] columns: positive integer + assert_equals: The value should be 3 at 0ms expected "3" but got "auto 3" +[FAIL] columns: length + assert_equals: The value should be 20px at 0ms expected "20px" but got "20px auto" +[FAIL] columns: length of rem + assert_equals: The value should be 20px at 0ms expected "20px" but got "20px auto" +[FAIL] flex-flow: "row" onto "row-reverse wrap" + assert_equals: The value should be row at 0ms expected "row" but got "row nowrap" +[FAIL] font-style: "oblique" onto "italic" + assert_equals: The value should be oblique at 0ms expected "oblique" but got "italic" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001-expected.txt b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001-expected.txt new file mode 100644 index 0000000..4fc1e1d --- /dev/null +++ b/third_party/blink/web_tests/virtual/css-gap-decorations-disabled/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-001-expected.txt
@@ -0,0 +1,34 @@ +This is a testharness.js-based test. +Found 15 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with linear easing + assert_equals: The value should be url("http://localhost/test-1") at 499ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 50.1%, url(\\"http://localhost/test-2\\"))" +[FAIL] background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing + assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 57.1741%, url(\\"http://localhost/test-2\\"))" +[FAIL] background-image uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing + assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 57.1741%, url(\\"http://localhost/test-2\\"))" +[FAIL] border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with linear easing + assert_equals: The value should be url("http://localhost/test-1") at 499ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 50.1%, url(\\"http://localhost/test-2\\"))" +[FAIL] border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with effect easing + assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 57.1741%, url(\\"http://localhost/test-2\\"))" +[FAIL] border-image-source uses discrete animation when animating between "url("http://localhost/test-1")" and "url("http://localhost/test-2")" with keyframe easing + assert_equals: The value should be url("http://localhost/test-1") at 940ms expected "url(\\"http://localhost/test-1\\")" but got "cross-fade(url(\\"http://localhost/test-1\\") 57.1741%, url(\\"http://localhost/test-2\\"))" +[FAIL] columns supports animating as a positive integer + assert_equals: The value should be 2 at 500ms expected "2" but got "auto 2" +[FAIL] columns supports animating as a length + assert_equals: The value should be 30px at 500ms expected "30px" but got "30px auto" +[FAIL] columns supports animating as a length of rem + assert_equals: The value should be 30px at 500ms expected "30px" but got "30px auto" +[FAIL] flex-flow uses discrete animation when animating between "row" and "row-reverse wrap" with linear easing + assert_equals: The value should be row at 0ms expected "row" but got "row nowrap" +[FAIL] flex-flow uses discrete animation when animating between "row" and "row-reverse wrap" with effect easing + assert_equals: The value should be row at 0ms expected "row" but got "row nowrap" +[FAIL] flex-flow uses discrete animation when animating between "row" and "row-reverse wrap" with keyframe easing + assert_equals: The value should be row at 0ms expected "row" but got "row nowrap" +[FAIL] font-style uses discrete animation when animating between "italic" and "oblique" with linear easing + assert_equals: The value should be oblique at 500ms expected "oblique" but got "italic" +[FAIL] font-style uses discrete animation when animating between "italic" and "oblique" with effect easing + assert_equals: The value should be oblique at 960ms expected "oblique" but got "italic" +[FAIL] font-style uses discrete animation when animating between "italic" and "oblique" with keyframe easing + assert_equals: The value should be oblique at 960ms expected "oblique" but got "italic" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations/README.md b/third_party/blink/web_tests/virtual/css-gap-decorations/README.md deleted file mode 100644 index a651a8e..0000000 --- a/third_party/blink/web_tests/virtual/css-gap-decorations/README.md +++ /dev/null
@@ -1 +0,0 @@ -Testing CSSGapDecorations; see ../../VirtualTestSuites
diff --git a/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-shorthand-expected.txt b/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-shorthand-expected.txt deleted file mode 100644 index d2490db..0000000 --- a/third_party/blink/web_tests/virtual/css-gap-decorations/external/wpt/css/css-multicol/parsing/column-rule-shorthand-expected.txt +++ /dev/null
@@ -1,3 +0,0 @@ -This is a testharness.js-based test. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/overscroll-behavior-all-scroll-containers/README.md b/third_party/blink/web_tests/virtual/overscroll-behavior-all-scroll-containers/README.md new file mode 100644 index 0000000..3378b32 --- /dev/null +++ b/third_party/blink/web_tests/virtual/overscroll-behavior-all-scroll-containers/README.md
@@ -0,0 +1,3 @@ +# Overview + +This suite tests with `--enable-features=OverscrollBehaviorRespectedOnAllScrollContainers`.
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/element-shadow-ref.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-ref.html rename to third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/element-shadow-ref.html
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/element-shadow.html similarity index 93% rename from third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow.html rename to third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/element-shadow.html index aba45e8..3cbf8f6 100644 --- a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow.html +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/element-shadow.html
@@ -3,7 +3,7 @@ <title>Canvas.drawElement: element with shadows on all sides clips to border box rect</title> <link rel="help" href="https://github.com/WICG/html-in-canvas"> <link rel="author" href="mailto:chrishtr@chromium.org"> -<link rel="match" href="shadow-ref.html"> +<link rel="match" href="element-shadow-ref.html"> <script src="/common/reftest-wait.js"></script> <style> #child {
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic-ref.html new file mode 100644 index 0000000..153c6e679 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic-ref.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> +<title>Canvas.drawElement: green rect with shadow (ref)</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<style> +#canvas { + background: grey; +} +</style> + +<canvas id=canvas width="200" height="200" layoutsubtree> +</canvas> + +<script> +function runTest() { + var context = canvas.getContext("2d"); + context.fillStyle = "green"; + context.shadowColor = "black"; + context.shadowBlur = 5; + context.shadowOffsetX = 20; + context.shadowOffsetY = 10; + context.fillRect(20, 30, 100, 100); +} + +onload = () => runTest(); + +</script> +</html>
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic.html new file mode 100644 index 0000000..368088d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/shadow-basic.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<html> +<title>Canvas.drawElement: green rect with shadow</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="shadow-basic-ref.html"> +<meta name=fuzzy content="2;1989"> +<style> +#child { + width: 100px; + height: 100px; + background: green; +} +#canvas { + background: grey; +} +</style> + +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id=child></div> +</canvas> + +<script> +function runTest() { + var context = canvas.getContext("2d"); + context.shadowColor = "black"; + context.shadowBlur = 5; + context.shadowOffsetX = 20; + context.shadowOffsetY = 10; + context.drawElement(child, 20, 30); +} + +onload = () => runTest(); + +</script> +</html>
diff --git a/third_party/boringssl/src b/third_party/boringssl/src index 860c270..f51d8b0 160000 --- a/third_party/boringssl/src +++ b/third_party/boringssl/src
@@ -1 +1 @@ -Subproject commit 860c27038fcd9c2c27242e9874c18408dec1f84c +Subproject commit f51d8b099832f805022a6ff2e9466dbcacdfb0ab
diff --git a/third_party/catapult b/third_party/catapult index 116ec83..a03b709 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 116ec83ba82d63aeb64fc56a4b0912947492f1df +Subproject commit a03b70978cc52840b549947f0fb165f03764c700
diff --git a/third_party/dawn b/third_party/dawn index 3f5a9376..5602ae0 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 3f5a9376dea63b041f604afef820651213272a9d +Subproject commit 5602ae03628ac1ae4ba8d265ac1979abea42d6ba
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index f5f6ac5..b019617 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit f5f6ac59025c9c34c1626573d6b5f77f804509ba +Subproject commit b0196172485ea5c6606d909d19a4e066ee32c004
diff --git a/third_party/fuzztest/src b/third_party/fuzztest/src index 6c64b55..45a1c3a 160000 --- a/third_party/fuzztest/src +++ b/third_party/fuzztest/src
@@ -1 +1 @@ -Subproject commit 6c64b55603eab828e5acb92d40cf92c663194fb2 +Subproject commit 45a1c3ad5ac3de58c8e9a3f89036e3f954820d4c
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium index 28773e3..c1c154d 100644 --- a/third_party/libaom/README.chromium +++ b/third_party/libaom/README.chromium
@@ -2,7 +2,7 @@ Short Name: libaom URL: https://aomedia.googlesource.com/aom/ Version: N/A -Revision: 6c4010bde34318fd6c1f0d10196f27ac9908eeb8 +Revision: 0ddc6630b3723b14b164752d46c27752f078ddd3 CPEPrefix: cpe:/a:aomedia:aomedia:3.12.1 License: BSD-2-Clause, Patent License Android Compatible: yes
diff --git a/third_party/libaom/libaom_srcs.gni b/third_party/libaom/libaom_srcs.gni index b66b4adc..57fca10 100644 --- a/third_party/libaom/libaom_srcs.gni +++ b/third_party/libaom/libaom_srcs.gni
@@ -146,6 +146,7 @@ "//third_party/libaom/source/libaom/av1/common/scan.h", "//third_party/libaom/source/libaom/av1/common/seg_common.c", "//third_party/libaom/source/libaom/av1/common/seg_common.h", + "//third_party/libaom/source/libaom/av1/common/selfguided_hwy.h", "//third_party/libaom/source/libaom/av1/common/thread_common.c", "//third_party/libaom/source/libaom/av1/common/thread_common.h", "//third_party/libaom/source/libaom/av1/common/tile_common.c",
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h index 1225abc6..1a6287d 100644 --- a/third_party/libaom/source/config/config/aom_version.h +++ b/third_party/libaom/source/config/config/aom_version.h
@@ -14,9 +14,9 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 12 #define VERSION_PATCH 1 -#define VERSION_EXTRA "182-g6c4010bde3" +#define VERSION_EXTRA "189-g0ddc6630b3" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "3.12.1-182-g6c4010bde3" -#define VERSION_STRING " 3.12.1-182-g6c4010bde3" +#define VERSION_STRING_NOSP "3.12.1-189-g0ddc6630b3" +#define VERSION_STRING " 3.12.1-189-g0ddc6630b3" #endif // AOM_VERSION_H_
diff --git a/third_party/libaom/source/libaom b/third_party/libaom/source/libaom index 6c4010b..0ddc663 160000 --- a/third_party/libaom/source/libaom +++ b/third_party/libaom/source/libaom
@@ -1 +1 @@ -Subproject commit 6c4010bde34318fd6c1f0d10196f27ac9908eeb8 +Subproject commit 0ddc6630b3723b14b164752d46c27752f078ddd3
diff --git a/third_party/perfetto b/third_party/perfetto index 9d9c4e7..21d660f 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 9d9c4e778b7867127e336d7560ddb49525b12faf +Subproject commit 21d660f5550822d7bcf79c43595ffbf258fe681a
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src index c837be3..85607567 160000 --- a/third_party/spirv-tools/src +++ b/third_party/spirv-tools/src
@@ -1 +1 @@ -Subproject commit c837be3e42a61a69a07c959ffc95871bf5a16525 +Subproject commit 85607567adde930f1598024116caa1ff9831848c
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index 0dbbf0d..565c281 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit 0dbbf0da762246640feffd8182cf1276c20ee898 +Subproject commit 565c281d73214e4712bd78be4cb7ccc2833ea471
diff --git a/tools/binary_size/libsupersize/native.py b/tools/binary_size/libsupersize/native.py index 072cace..d3e17ef 100644 --- a/tools/binary_size/libsupersize/native.py +++ b/tools/binary_size/libsupersize/native.py
@@ -804,7 +804,10 @@ with tempfile.NamedTemporaryFile( suffix=os.path.basename(native_spec.elf_path)) as f: strip_path = path_util.GetStripPath() - subprocess.run([strip_path, '-o', f.name, native_spec.elf_path], + subprocess.run([ + strip_path, '--strip-debug', '--strip-unneeded', '-o', f.name, + native_spec.elf_path + ], check=True) elf_info = _CreateElfInfo(f.name)
diff --git a/tools/binary_size/libsupersize/path_util.py b/tools/binary_size/libsupersize/path_util.py index 493a012..0969aed 100644 --- a/tools/binary_size/libsupersize/path_util.py +++ b/tools/binary_size/libsupersize/path_util.py
@@ -172,13 +172,11 @@ def GetStripPath(): - # Chromium's toolchain uses //buildtools/third_party/eu-strip, but first - # look for the test-only "fakestrip" for the sake of tests. + # First look for the test-only "fakestrip" for the sake of tests. fake_strip = _LlvmTool('fakestrip') if os.path.exists(fake_strip): return fake_strip - return FromToolsSrcRoot('buildtools', 'third_party', 'eu-strip', 'bin', - 'eu-strip') + return _LlvmTool('strip') def GetApkAnalyzerPath():
diff --git a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_fakestrip.py b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_fakestrip.py index 782619a7..0d7739a 100644 --- a/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_fakestrip.py +++ b/tools/binary_size/libsupersize/testdata/mock_toolchain/mock_fakestrip.py
@@ -9,6 +9,8 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('-o', dest='output', required=True) + parser.add_argument('--strip-debug', action='store_true') + parser.add_argument('--strip-unneeded', action='store_true') parser.add_argument('input') args = parser.parse_args() shutil.copy(args.input, args.output)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 6dbf03b..252f07c 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -16810,6 +16810,7 @@ <int value="1072517479" label="ImprovedCookieControls:enabled"/> <int value="1073143086" label="TopControlsRefactor:disabled"/> <int value="1073699828" label="ScrollUpdateOptimizations:enabled"/> + <int value="1074310931" label="OmniboxMobileParityUpdateV2:disabled"/> <int value="1074359194" label="UseSuggestionsEvenIfFew:enabled"/> <int value="1074427701" label="NewPrintPreviewLayout:enabled"/> <int value="1075191614" label="LauncherSystemInfoAnswerCards:disabled"/> @@ -18648,6 +18649,7 @@ <int value="1736698988" label="FsNosymfollow:disabled"/> <int value="1737406099" label="TrustSafetySentimentSurvey:disabled"/> <int value="1738520473" label="SystemTrayMicGainSetting:disabled"/> + <int value="1739253215" label="OmniboxMobileParityUpdateV2:enabled"/> <int value="1739456903" label="PWAFullCodeCache:enabled"/> <int value="1739507233" label="EarlyEstablishGpuChannel:enabled"/> <int value="1739782037" label="LinkDoctorDeprecationAndroid:enabled"/>
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml index f8c859bb..dfa2c3d 100644 --- a/tools/metrics/histograms/metadata/blink/enums.xml +++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -4198,30 +4198,37 @@ <int value="3750" label="PaymentHandlerStandardizedPaymentMethodIdentifier"/> <int value="3751" label="WebCodecsAudioEncoder"/> <int value="3752" label="EmbeddedCrossOriginFrameWithoutFrameAncestorsOrXFO"/> - <int value="3753" label="AddressSpacePrivateSecureContextEmbeddedLocal"/> - <int value="3754" label="AddressSpacePrivateNonSecureContextEmbeddedLocal"/> - <int value="3755" label="AddressSpacePublicSecureContextEmbeddedLocal"/> - <int value="3756" label="AddressSpacePublicNonSecureContextEmbeddedLocal"/> - <int value="3757" label="AddressSpacePublicSecureContextEmbeddedPrivate"/> - <int value="3758" label="AddressSpacePublicNonSecureContextEmbeddedPrivate"/> - <int value="3759" label="AddressSpaceUnknownSecureContextEmbeddedLocal"/> - <int value="3760" label="AddressSpaceUnknownNonSecureContextEmbeddedLocal"/> - <int value="3761" label="AddressSpaceUnknownSecureContextEmbeddedPrivate"/> - <int value="3762" label="AddressSpaceUnknownNonSecureContextEmbeddedPrivate"/> - <int value="3763" label="AddressSpacePrivateSecureContextNavigatedToLocal"/> + <int value="3753" label="AddressSpaceLocalSecureContextEmbeddedLoopbackV2"/> + <int value="3754" + label="AddressSpaceLocalNonSecureContextEmbeddedLoopbackV2"/> + <int value="3755" label="AddressSpacePublicSecureContextEmbeddedLoopbackV2"/> + <int value="3756" + label="AddressSpacePublicNonSecureContextEmbeddedLoopbackV2"/> + <int value="3757" label="AddressSpacePublicSecureContextEmbeddedLocalV2"/> + <int value="3758" label="AddressSpacePublicNonSecureContextEmbeddedLocalV2"/> + <int value="3759" label="AddressSpaceUnknownSecureContextEmbeddedLoopbackV2"/> + <int value="3760" + label="AddressSpaceUnknownNonSecureContextEmbeddedLoopbackV2"/> + <int value="3761" label="AddressSpaceUnknownSecureContextEmbeddedLocalV2"/> + <int value="3762" label="AddressSpaceUnknownNonSecureContextEmbeddedLocalV2"/> + <int value="3763" + label="AddressSpaceLocalSecureContextNavigatedToLoopbackV2"/> <int value="3764" - label="AddressSpacePrivateNonSecureContextNavigatedToLocal"/> - <int value="3765" label="AddressSpacePublicSecureContextNavigatedToLocal"/> - <int value="3766" label="AddressSpacePublicNonSecureContextNavigatedToLocal"/> - <int value="3767" label="AddressSpacePublicSecureContextNavigatedToPrivate"/> + label="AddressSpaceLocalNonSecureContextNavigatedToLoopbackV2"/> + <int value="3765" + label="AddressSpacePublicSecureContextNavigatedToLoopbackV2"/> + <int value="3766" + label="AddressSpacePublicNonSecureContextNavigatedToLoopbackV2"/> + <int value="3767" label="AddressSpacePublicSecureContextNavigatedToLocalV2"/> <int value="3768" - label="AddressSpacePublicNonSecureContextNavigatedToPrivate"/> - <int value="3769" label="AddressSpaceUnknownSecureContextNavigatedToLocal"/> + label="AddressSpacePublicNonSecureContextNavigatedToLocalV2"/> + <int value="3769" + label="AddressSpaceUnknownSecureContextNavigatedToLoopbackV2"/> <int value="3770" - label="AddressSpaceUnknownNonSecureContextNavigatedToLocal"/> - <int value="3771" label="AddressSpaceUnknownSecureContextNavigatedToPrivate"/> + label="AddressSpaceUnknownNonSecureContextNavigatedToLoopbackV2"/> + <int value="3771" label="AddressSpaceUnknownSecureContextNavigatedToLocalV2"/> <int value="3772" - label="AddressSpaceUnknownNonSecureContextNavigatedToPrivate"/> + label="AddressSpaceUnknownNonSecureContextNavigatedToLocalV2"/> <int value="3773" label="OBSOLETE_RTCPeerConnectionSdpSemanticsPlanB"/> <int value="3774" label="FetchRespondWithNoResponseWithUsedRequestBody"/> <int value="3775" label="V8TCPSocket_Close_Method"/> @@ -6218,6 +6225,7 @@ <int value="5593" label="V8URLPattern_Generate_Method"/> <int value="5594" label="SelectMultipleSizeOne"/> <int value="5595" label="WebGPUFeatureLevelCompatibility"/> + <int value="5596" label="OverscrollBehaviorOnNonScrollableScrollContainer"/> </enum> <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
diff --git a/tools/metrics/histograms/metadata/new_tab_page/enums.xml b/tools/metrics/histograms/metadata/new_tab_page/enums.xml index 10b1c82..1483a2e8 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/enums.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/enums.xml
@@ -52,6 +52,10 @@ <int value="4" label="The native page is frozen"/> </enum> +<enum name="FooterContextMenuItem"> + <int value="0" label="Hide footer clicked."/> +</enum> + <enum name="FooterCustomizeChromeEntryPoint"> <int value="0" label="Customize Chrome button clicked."/> <int value="1" label="NTP URL has customize chrome parameters."/> @@ -59,11 +63,12 @@ </enum> <enum name="FooterElement"> - <int value="0" label="Other Element"/> - <int value="1" label="Customize Chrome Button"/> - <int value="2" label="Extension name"/> - <int value="3" label="Management notice"/> - <int value="4" label="Background name"/> + <int value="0" label="Other Element clicked"/> + <int value="1" label="Customize Chrome Button clicked"/> + <int value="2" label="Extension name clicked"/> + <int value="3" label="Management notice clicked"/> + <int value="4" label="Background name clicked"/> + <int value="5" label="Context menu opened"/> </enum> <enum name="ItemSuggestRequestResult">
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml index 10ba343..03a5216 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -584,7 +584,9 @@ <owner>xinyiji@chromium.org</owner> <summary> Record the total number of impressions of the fake search box on the New Tab - Page. The histogram is logged on New tab page and is Android-only. + Page. This logs a baseline impression count for the button in the fake + search box. The event is triggered each time the New Tab Page is shown or + the button's visibility is updated.The histogram is Android-only. </summary> </histogram> @@ -596,6 +598,14 @@ <summary>Logged when the Footer was clicked.</summary> </histogram> +<histogram name="NewTabPage.Footer.ContextMenuClicked" + enum="FooterContextMenuItem" expires_after="2025-11-23"> + <owner>temao@chromium.org</owner> + <owner>tiborg@chromium.org</owner> + <owner>chrome-desktop-ntp@google.com</owner> + <summary>Logged when item in footer's context menu is clicked.</summary> +</histogram> + <histogram name="NewTabPage.Footer.CustomizeChromeOpened" enum="FooterCustomizeChromeEntryPoint" expires_after="2025-11-23"> <owner>temao@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index ee3f77d..b9fc3f4 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -1386,6 +1386,20 @@ <token key="ProfileType" variants="ProfileType"/> </histogram> +<histogram name="PasswordManager.CredentialRequest.Get.Success" + enum="BooleanSuccess" expires_after="2025-12-20"> + <owner>izuzic@google.com</owner> + <owner>anki-team@google.com</owner> + <summary> + Log the result of the call to the Credential Manager API when getting a + credential. This is an aggregated histogram for first and third party calls. + Success means that all works as intended and not necessarily that the + password store or Android API was queried. We sometimes immediately return + an empty credential, for example in incognito mode, so the success rate + could be higher than the actual usage of the password store or the API. + </summary> +</histogram> + <histogram name="PasswordManager.CredentialRequest.ThirdParty.Get" enum="CredentialManagerAndroidGetResult" expires_after="2025-12-11"> <owner>izuzic@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml index 844d52c..3f00711 100644 --- a/tools/metrics/histograms/metadata/sb_client/histograms.xml +++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -461,7 +461,7 @@ </histogram> <histogram name="SBClientPhishing.BrowserReadyOnClassifierNotReady" - enum="BooleanReady" expires_after="2025-07-24"> + enum="BooleanReady" expires_after="2026-07-24"> <owner>andysjlim@chromium.org</owner> <owner>chrome-counter-abuse-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index f2a09df4..b47d0e9 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -3514,6 +3514,20 @@ quality. They are recorded on navigation if a form was submitted before, only if the submitted form had Autofill AI prediction. </summary> + <metric name="AutofillAiFilledFieldCount"> + <summary> + The number of fields at form submission that are autofilled and that were + autofilled by AutofillAi. Fields filled with any other source will be + excluded from this count. + </summary> + </metric> + <metric name="AutofillFilledFieldCount"> + <summary> + The number of fields at form submission that are autofilled. This will + include fields that are autofilled by any source except Autocomplete, + including AutofillAi. + </summary> + </metric> <metric name="FillingAcceptance"> <summary> Has value 1 if user accepted the suggestion to fill values on a submitted
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 0810069..f80c902 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/3940ed807f48affbec08603c79e957d10e4a6ef4/linux-arm64/trace_processor_shell" }, "win": { - "hash": "ca751629c1454ea64e1ba81e6a7279b4b1bc0659", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/2cec679e5a52f412004699707516cc7127419aa9/trace_processor_shell.exe" + "hash": "ca33458e191a3a1a54300c3f2e6df7463cbd02f1", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b6d5ffb271cc26946597529583efb3a4a2c967dc/trace_processor_shell.exe" }, "linux_arm": { "hash": "be8386e1db86d436e39624fdbcff5b6586bedfdd",
diff --git a/ui/accessibility/platform/browser_accessibility_manager.cc b/ui/accessibility/platform/browser_accessibility_manager.cc index 92575c7..57b9318 100644 --- a/ui/accessibility/platform/browser_accessibility_manager.cc +++ b/ui/accessibility/platform/browser_accessibility_manager.cc
@@ -2008,7 +2008,8 @@ return node_id_delegate_->GetOrCreateAXNodeUniqueId(node->node()->id()); } -BrowserAccessibility* BrowserAccessibilityManager::GetAccessibilityFocus() { +BrowserAccessibility* BrowserAccessibilityManager::GetAccessibilityFocus() + const { if (accessibility_focus_tree_id_ == AXTreeIDUnknown() || accessibility_focus_node_id_ == AXNodeData::kInvalidAXID) { return nullptr;
diff --git a/ui/accessibility/platform/browser_accessibility_manager.h b/ui/accessibility/platform/browser_accessibility_manager.h index d64079a6..b2b6a63 100644 --- a/ui/accessibility/platform/browser_accessibility_manager.h +++ b/ui/accessibility/platform/browser_accessibility_manager.h
@@ -504,7 +504,7 @@ AXPlatformNodeId GetNodeUniqueId(const BrowserAccessibility* node); // Returns the global accessibility focus. Only relevant on a root manager. - BrowserAccessibility* GetAccessibilityFocus(); + virtual BrowserAccessibility* GetAccessibilityFocus() const; protected: FRIEND_TEST_ALL_PREFIXES(content::BrowserAccessibilityManagerTest,
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index c037feb..2d02a47 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -268,7 +268,6 @@ "java/res/drawable/transition_expand_less_expand_more_black_24dp.xml", "java/res/drawable/transition_expand_more_expand_less_black_24dp.xml", "java/res/font/accent_font.xml", - "java/res/layout-v28/list_section_divider.xml", "java/res/layout/custom_toast_layout.xml", "java/res/layout/dropdown_item.xml", "java/res/layout/horizontal_divider.xml",
diff --git a/ui/android/java/res/layout-v28/list_section_divider.xml b/ui/android/java/res/layout-v28/list_section_divider.xml deleted file mode 100644 index 13d1abd..0000000 --- a/ui/android/java/res/layout-v28/list_section_divider.xml +++ /dev/null
@@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -Copyright 2025 The Chromium Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. ---> -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="@dimen/list_section_divider_padding" - android:paddingBottom="@dimen/list_section_divider_padding" - android:focusable="false" - android:screenReaderFocusable="false"> - <include layout="@layout/horizontal_divider" /> -</FrameLayout> \ No newline at end of file
diff --git a/ui/android/java/res/layout/list_section_divider.xml b/ui/android/java/res/layout/list_section_divider.xml index 40bd953..86e6e071 100644 --- a/ui/android/java/res/layout/list_section_divider.xml +++ b/ui/android/java/res/layout/list_section_divider.xml
@@ -10,6 +10,7 @@ android:layout_height="wrap_content" android:paddingTop="@dimen/list_section_divider_padding" android:paddingBottom="@dimen/list_section_divider_padding" - android:importantForAccessibility="no" > + android:focusable="false" + android:screenReaderFocusable="false"> <include layout="@layout/horizontal_divider" /> </FrameLayout> \ No newline at end of file
diff --git a/ui/base/prediction/linear_resampling.cc b/ui/base/prediction/linear_resampling.cc index 2658827..4b53186 100644 --- a/ui/base/prediction/linear_resampling.cc +++ b/ui/base/prediction/linear_resampling.cc
@@ -27,11 +27,6 @@ // so that resampled result is more accurate and has less noise. This adds some // latency during resampling but a few ms should be fine. constexpr auto kResampleLatency = base::Milliseconds(-5); -// The optimal prediction anticipation from experimentation: In the study -// https://bit.ly/3iyQf8V we found that, on a machine with VSync at 60Hz, adding -// 1/2 * frame_interval (on top of kResampleLatency) minimizes the Lag on touch -// scrolling. + 1/2 * (1/60) - 5ms = 3.3ms. -constexpr auto kResampleLatencyExperimental = base::Milliseconds(3.3); // Get position at |sample_time| by linear interpolate/extrapolate a and b. inline gfx::PointF lerp(const InputPredictor::InputData& a, @@ -126,26 +121,23 @@ std::string prediction_type = GetFieldTrialParamValueByFeature( ::features::kResamplingScrollEventsExperimentalPrediction, "mode"); - std::string latency_value = GetFieldTrialParamValueByFeature( - ::features::kResamplingScrollEventsExperimentalPrediction, "latency"); - - TRACE_EVENT2("ui", "LatencyCalculator::CalculateLatency", "prediction_type", - prediction_type, "latency_value", latency_value); - - if (prediction_type != ::features::kPredictionTypeTimeBased && - prediction_type != ::features::kPredictionTypeFramesBased) + if (prediction_type != ::features::kPredictionTypeFramesBased) { + TRACE_EVENT1("ui", "LatencyCalculator::CalculateLatency", "prediction_type", + "default"); return kResampleLatency; - - double latency; - if (base::StringToDouble(latency_value, &latency)) { - return prediction_type == ::features::kPredictionTypeTimeBased - ? base::Milliseconds(latency) - : latency * frame_interval_ + kResampleLatency; } - return prediction_type == ::features::kPredictionTypeTimeBased - ? kResampleLatencyExperimental - : 0.5 * frame_interval_ + kResampleLatency; + double latency = 0; + if (!base::StringToDouble( + GetFieldTrialParamValueByFeature( + ::features::kResamplingScrollEventsExperimentalPrediction, + "latency"), + &latency)) { + latency = 0.5; + } + TRACE_EVENT2("ui", "LatencyCalculator::CalculateLatency", "prediction_type", + prediction_type, "latency", latency); + return latency * frame_interval_ + kResampleLatency; } } // namespace ui
diff --git a/ui/base/prediction/linear_resampling_unittest.cc b/ui/base/prediction/linear_resampling_unittest.cc index 24d929f..be0e940 100644 --- a/ui/base/prediction/linear_resampling_unittest.cc +++ b/ui/base/prediction/linear_resampling_unittest.cc
@@ -164,50 +164,6 @@ EXPECT_EQ(predictor_->TimeInterval(), base::Milliseconds(t[1] - t[0])); } -// Tests resampling with the experimental latency if +3.3ms instead of -// the default -5ms. -TEST_F(LinearResamplingTest, ResamplingValueWithExperimentalLatencyTimeBased) { - base::FieldTrialParams params; - params["mode"] = ::features::kPredictionTypeTimeBased; - feature_list.Reset(); - feature_list.InitAndEnableFeatureWithParameters( - features::kResamplingScrollEventsExperimentalPrediction, params); - - std::vector<double> x = {10, 20, 30}; - std::vector<double> y = {5, 25, 35}; - std::vector<double> t = {15, 24, 32}; - - // Resample at `frame_time` = 24.7 ms, `sample_time` = 24.7+3.3 = 28ms. - // Resample at `frame_time` = 32.7 ms, `sample_time` = 32.7+3.3 = 36ms. - std::vector<double> pred_ts = {24.7, 32.7}; - std::vector<double> pred_x = {24.44, 35}; - std::vector<double> pred_y = {33.89, 40}; - ValidatePredictor(x, y, t, pred_ts, pred_x, pred_y); -} - -// Tests resampling with the experimental latency if +1ms (using switch) instead -// of the default -5ms. -TEST_F(LinearResamplingTest, - ResamplingValueWithExperimentalLatencyTimeBasedSwitch) { - base::FieldTrialParams params; - params["mode"] = ::features::kPredictionTypeTimeBased; - params["latency"] = "1.0"; - feature_list.Reset(); - feature_list.InitAndEnableFeatureWithParameters( - features::kResamplingScrollEventsExperimentalPrediction, params); - - std::vector<double> x = {10, 20, 30}; - std::vector<double> y = {5, 25, 35}; - std::vector<double> t = {15, 24, 32}; - - // Resample at `frame_time` = 27 ms, `sample_time` = 27+1 = 28ms. - // Resample at `frame_time` = 35 ms, `sample_time` = 35+1 = 36ms. - std::vector<double> pred_ts = {27, 35}; - std::vector<double> pred_x = {24.44, 35}; - std::vector<double> pred_y = {33.89, 40}; - ValidatePredictor(x, y, t, pred_ts, pred_x, pred_y); -} - // Tests resampling with the experimental latency if +0.5*`frame_interval` // instead of the default -5ms. TEST_F(LinearResamplingTest, ResamplingValueWithExperimentalLatencyFrameBased) {
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 20a312a..bbe7831 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -370,9 +370,7 @@ const char kFilterNameEmpty[] = "empty_filter"; const char kFilterNameOneEuro[] = "one_euro_filter"; -const char kPredictionTypeTimeBased[] = "time"; const char kPredictionTypeFramesBased[] = "frames"; -const char kPredictionTypeDefaultTime[] = "3.3"; const char kPredictionTypeDefaultFramesVariation1[] = "0.25"; const char kPredictionTypeDefaultFramesVariation2[] = "0.375"; const char kPredictionTypeDefaultFramesVariation3[] = "0.5";
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 7e82d0e..414e91b 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -163,15 +163,10 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kResamplingScrollEventsExperimentalPrediction); -// The type of prediction used. TimeBased uses a fixed timing, FramesBased uses -// a ratio of the vsync refresh rate. The timing/ratio can be changed on the -// command line through a `latency` param. -COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictionTypeTimeBased[]; +// Uses a ratio of the vsync refresh rate. The timing/ratio can be changed on +// the command line through a `latency` param. COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictionTypeFramesBased[]; -// The default values for `latency` -COMPONENT_EXPORT(UI_BASE_FEATURES) -extern const char kPredictionTypeDefaultTime[]; COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictionTypeDefaultFramesVariation1[]; COMPONENT_EXPORT(UI_BASE_FEATURES)
diff --git a/ui/events/android/key_event_android.h b/ui/events/android/key_event_android.h index 2bc408f..34ffae4 100644 --- a/ui/events/android/key_event_android.h +++ b/ui/events/android/key_event_android.h
@@ -40,4 +40,22 @@ } // namespace ui +namespace jni_zero { + +// @JniType conversion function. +template <> +inline ui::KeyEventAndroid FromJniType<ui::KeyEventAndroid>( + JNIEnv* env, + const JavaRef<jobject>& j_obj) { + return ui::KeyEventAndroid(env, j_obj.obj()); +} +template <> +inline ScopedJavaLocalRef<jobject> ToJniType<ui::KeyEventAndroid>( + JNIEnv* env, + const ui::KeyEventAndroid& obj) { + return obj.GetJavaObject(); +} + +} // namespace jni_zero + #endif // UI_EVENTS_ANDROID_KEY_EVENT_ANDROID_H_
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index 191068f..0f403e2 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -249,8 +249,6 @@ "win/text_analysis_source.h", "win/window_impl.cc", "win/window_impl.h", - "win/wuc_backdrop.cc", - "win/wuc_backdrop.h", ] } if (is_apple) {
diff --git a/ui/gfx/win/wuc_backdrop.cc b/ui/gfx/win/wuc_backdrop.cc deleted file mode 100644 index 9af658d3..0000000 --- a/ui/gfx/win/wuc_backdrop.cc +++ /dev/null
@@ -1,154 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/gfx/win/wuc_backdrop.h" - -#include <DispatcherQueue.h> -#include <windows.ui.composition.core.h> -#include <wrl/client.h> - -#include "base/debug/dump_without_crashing.h" -#include "base/logging.h" -#include "base/scoped_native_library.h" -#include "base/threading/sequence_local_storage_slot.h" -#include "base/threading/thread_restrictions.h" -#include "base/win/core_winrt_util.h" -#include "base/win/hstring_reference.h" - -namespace gfx { - -namespace { -using Microsoft::WRL::ComPtr; -using CreateDispatcherQueueControllerProc = - decltype(&::CreateDispatcherQueueController); -namespace WUC = ABI::Windows::UI::Composition; - -CreateDispatcherQueueControllerProc GetOrCreateDispatcherQueueControllerProc() { - static CreateDispatcherQueueControllerProc const function = - reinterpret_cast<CreateDispatcherQueueControllerProc>( - WUCBackdrop::LoadCoreMessagingFunction( - "CreateDispatcherQueueController")); - return function; -} - -HRESULT GetDispatcherQueueController( - DispatcherQueueOptions options, - ABI::Windows::System::IDispatcherQueueController** controller) { - CreateDispatcherQueueControllerProc create_dispatcher_queue_controller_func = - GetOrCreateDispatcherQueueControllerProc(); - CHECK(create_dispatcher_queue_controller_func); - return create_dispatcher_queue_controller_func(options, controller); -} - -bool EnsurePerThreadDispatcherQueueController() { - // Maintain one DispatcherQueueController per thread. - // DispatcherQueueController and its associated DispatcherQueue will be kept - // alive by the OS while the event loop is running. - static base::SequenceLocalStorageSlot< - Microsoft::WRL::ComPtr<ABI::Windows::System::IDispatcherQueueController>> - queue_controller_slot; - - if (queue_controller_slot) { - return true; - } - - ComPtr<ABI::Windows::System::IDispatcherQueueController> queue_controller; - HRESULT hr = GetDispatcherQueueController( - {sizeof(DispatcherQueueOptions), DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE}, - &queue_controller); - CHECK_EQ(hr, S_OK); - queue_controller_slot.emplace(std::move(queue_controller)); - return true; -} - -ComPtr<WUC::ICompositor> GetOrCreateCompositor() { - EnsurePerThreadDispatcherQueueController(); - // Maintain one Compositor per thread. SequenceLocalStorageSlot is - // needed because ICompositor has a non-trivial destructor. - static base::SequenceLocalStorageSlot<ComPtr<WUC::ICompositor>> - compositor_slot; - - if (compositor_slot) { - return *compositor_slot; - } - - ComPtr<WUC::ICompositor> compositor; - HRESULT hr = base::win::RoActivateInstance( - base::win::HStringReference( - RuntimeClass_Windows_UI_Composition_Compositor) - .Get(), - &compositor); - CHECK_EQ(hr, S_OK); - compositor_slot.emplace(compositor); - return compositor; -} -} // namespace - -WUCBackdrop::WUCBackdrop(HWND hwnd) { - ComPtr<WUC::ICompositor> compositor = GetOrCreateCompositor(); - - ComPtr<WUC::Desktop::ICompositorDesktopInterop> interop; - HRESULT hr = compositor.As(&interop); - CHECK_EQ(hr, S_OK); - - hr = interop->CreateDesktopWindowTarget(hwnd, /*isTopmost=*/false, - &desktop_window_target_); - CHECK_EQ(hr, S_OK); - - ComPtr<WUC::ICompositionTarget> wuc_composition_target; - hr = desktop_window_target_.As(&wuc_composition_target); - CHECK_EQ(hr, S_OK); - - hr = compositor->CreateSpriteVisual(&backdrop_sprite_visual_); - CHECK_EQ(hr, S_OK); - - ComPtr<WUC::IVisual> sprite_visual_as_visual; - hr = backdrop_sprite_visual_.As(&sprite_visual_as_visual); - CHECK_EQ(hr, S_OK); - hr = wuc_composition_target->put_Root(sprite_visual_as_visual.Get()); - CHECK_EQ(hr, S_OK); - - ComPtr<WUC::IVisual2> sprite_visual_as_visual2; - hr = sprite_visual_as_visual.As(&sprite_visual_as_visual2); - CHECK_EQ(hr, S_OK); - hr = sprite_visual_as_visual2->put_RelativeSizeAdjustment({1.0f, 1.0f}); - CHECK_EQ(hr, S_OK); -} - -void WUCBackdrop::UpdateBackdropColor(SkColor color) { - if (!solid_color_brush_) { - ComPtr<WUC::ICompositor> compositor = GetOrCreateCompositor(); - if (!compositor) { - return; - } - - HRESULT hr = compositor->CreateColorBrush(&solid_color_brush_); - CHECK_EQ(hr, S_OK); - - ComPtr<WUC::ICompositionBrush> brush; - hr = solid_color_brush_.As(&brush); - CHECK_EQ(hr, S_OK); - hr = backdrop_sprite_visual_->put_Brush(brush.Get()); - CHECK_EQ(hr, S_OK); - } - - HRESULT hr = - solid_color_brush_->put_Color({static_cast<BYTE>(SkColorGetA(color)), - static_cast<BYTE>(SkColorGetR(color)), - static_cast<BYTE>(SkColorGetG(color)), - static_cast<BYTE>(SkColorGetB(color))}); - CHECK_EQ(hr, S_OK); -} - -FARPROC WUCBackdrop::LoadCoreMessagingFunction(const char* function_name) { - static HMODULE handle = [] { - base::ScopedAllowBlocking scoped_allow_blocking; - return base::LoadSystemLibrary(L"CoreMessaging.dll"); - }(); - return handle ? ::GetProcAddress(handle, function_name) : nullptr; -} - -WUCBackdrop::~WUCBackdrop() = default; - -} // namespace gfx
diff --git a/ui/gfx/win/wuc_backdrop.h b/ui/gfx/win/wuc_backdrop.h deleted file mode 100644 index 89358f6..0000000 --- a/ui/gfx/win/wuc_backdrop.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_GFX_WIN_WUC_BACKDROP_H_ -#define UI_GFX_WIN_WUC_BACKDROP_H_ - -#include <windows.h> - -#include <windows.ui.composition.desktop.h> -#include <windows.ui.composition.h> -#include <windows.ui.composition.interop.h> -#include <wrl/client.h> - -#include "base/component_export.h" -#include "third_party/skia/include/core/SkColor.h" - -namespace gfx { - -// Creates a small Windows UI Composition (WUC) visual tree that serves as the -// backdrop for any HWND that is specified. -class COMPONENT_EXPORT(GFX) WUCBackdrop { - public: - WUCBackdrop(HWND hwnd); - ~WUCBackdrop(); - - // Takes an SkColor and applies it to the backdrop sprite visual. - void UpdateBackdropColor(SkColor color); - - // Load the CoreMessaging library and `function_name`. This function contains - // a blocking call. - static FARPROC LoadCoreMessagingFunction(const char* function_name); - - private: - // Represents the target of the WUC tree and retains a link to the root - // visual. - Microsoft::WRL::ComPtr< - ABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget> - desktop_window_target_; - // Sprite visuals take on color. This will be the leaf of the WUC tree and - // serve as the backdrop. Maintain a reference to the visual so that the - // visual is updated with browser theme. - Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ISpriteVisual> - backdrop_sprite_visual_; - // The color brush that will be used to color the backdrop sprite visual. - Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositionColorBrush> - solid_color_brush_; -}; - -} // namespace gfx - -#endif // UI_GFX_WIN_WUC_BACKDROP_H_
diff --git a/ui/views/accessibility/tree/widget_ax_manager.cc b/ui/views/accessibility/tree/widget_ax_manager.cc index 71b348da..6936c36 100644 --- a/ui/views/accessibility/tree/widget_ax_manager.cc +++ b/ui/views/accessibility/tree/widget_ax_manager.cc
@@ -11,7 +11,8 @@ namespace views { -WidgetAXManager::WidgetAXManager(Widget* widget) : widget_(widget) { +WidgetAXManager::WidgetAXManager(Widget* widget) + : widget_(widget), ax_tree_id_(ui::AXTreeID::CreateNewAXTreeID()) { CHECK(::features::IsAccessibilityTreeForViewsEnabled()) << "WidgetAXManager should only be created when the " "accessibility tree feature is enabled."; @@ -53,6 +54,16 @@ SchedulePendingUpdate(); } +void WidgetAXManager::OnChildAdded(WidgetAXManager* child_manager) { + CHECK(child_manager); + child_manager->parent_ax_tree_id_ = ax_tree_id_; +} + +void WidgetAXManager::OnChildRemoved(WidgetAXManager* child_manager) { + CHECK(child_manager); + child_manager->parent_ax_tree_id_ = ui::AXTreeID(); +} + void WidgetAXManager::OnAXModeAdded(ui::AXMode mode) { if (mode.has_mode(ui::AXMode::kNativeAPIs)) { Enable();
diff --git a/ui/views/accessibility/tree/widget_ax_manager.h b/ui/views/accessibility/tree/widget_ax_manager.h index 214f3f8..f36f6c1 100644 --- a/ui/views/accessibility/tree/widget_ax_manager.h +++ b/ui/views/accessibility/tree/widget_ax_manager.h
@@ -12,6 +12,7 @@ #include "base/memory/raw_ptr.h" #include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/accessibility/ax_node_id_forward.h" +#include "ui/accessibility/ax_tree_id.h" #include "ui/accessibility/platform/ax_mode_observer.h" #include "ui/views/views_export.h" @@ -37,6 +38,9 @@ void OnEvent(ViewAccessibility& view_ax, ax::mojom::Event event_type); void OnDataChanged(ViewAccessibility& view_ax); + void OnChildAdded(WidgetAXManager* child_manager); + void OnChildRemoved(WidgetAXManager* child_manager); + // ui::AXModeObserver: void OnAXModeAdded(ui::AXMode mode) override; @@ -49,6 +53,12 @@ // The widget this manager is owned by. raw_ptr<Widget> widget_; + // The AXTreeID for this widget's accessibility tree. Must be unique. + const ui::AXTreeID ax_tree_id_; + + // The AXTreeID of the parent widget's accessibility tree, if any. + ui::AXTreeID parent_ax_tree_id_; + // Indicates whether we're actively serializing widget accessibility data. bool is_enabled_ = false;
diff --git a/ui/views/accessibility/tree/widget_ax_manager_test_api.h b/ui/views/accessibility/tree/widget_ax_manager_test_api.h index b2380021..7d20afa 100644 --- a/ui/views/accessibility/tree/widget_ax_manager_test_api.h +++ b/ui/views/accessibility/tree/widget_ax_manager_test_api.h
@@ -22,6 +22,13 @@ return manager_->processing_update_posted_; } + const ui::AXTreeID& ax_tree_id() const { return manager_->ax_tree_id_; } + const ui::AXTreeID& parent_ax_tree_id() const { + return manager_->parent_ax_tree_id_; + } + + void TearDown() { manager_ = nullptr; } + private: raw_ptr<WidgetAXManager> manager_; };
diff --git a/ui/views/accessibility/tree/widget_ax_manager_unittest.cc b/ui/views/accessibility/tree/widget_ax_manager_unittest.cc index fd52ed0a..071950b0b 100644 --- a/ui/views/accessibility/tree/widget_ax_manager_unittest.cc +++ b/ui/views/accessibility/tree/widget_ax_manager_unittest.cc
@@ -60,6 +60,62 @@ EXPECT_TRUE(manager()->is_enabled()); } +TEST_F(WidgetAXManagerTest, InitParamsCreatesParentRelationship) { + WidgetAXManagerTestApi parent_api(manager()); + + std::unique_ptr<Widget> child_widget = + base::WrapUnique(CreateChildNativeWidgetWithParent( + widget(), Widget::InitParams::CLIENT_OWNS_WIDGET)); + auto* child_mgr = child_widget->ax_manager(); + WidgetAXManagerTestApi child_api(child_mgr); + + // The AX manager should have picked up the parent when Init() ran. + EXPECT_EQ(child_api.parent_ax_tree_id(), parent_api.ax_tree_id()); + + child_api.TearDown(); + + child_widget->CloseNow(); + child_widget.reset(); +} + +TEST_F(WidgetAXManagerTest, ReparentWidgetBetweenParents) { + WidgetAXManagerTestApi parent1_api(manager()); + + WidgetAutoclosePtr parent2(CreateTopLevelPlatformWidget()); + WidgetAXManagerTestApi parent2_api(parent2->ax_manager()); + + std::unique_ptr<Widget> child_widget = + base::WrapUnique(CreateChildNativeWidgetWithParent( + widget(), Widget::InitParams::CLIENT_OWNS_WIDGET)); + + WidgetAXManagerTestApi child_api(child_widget->ax_manager()); + EXPECT_EQ(child_api.parent_ax_tree_id(), parent1_api.ax_tree_id()); + + // Reparent via Widget::Reparent() should update the parent AXTreeID. + child_widget->Reparent(parent2.get()); + EXPECT_EQ(child_api.parent_ax_tree_id(), parent2_api.ax_tree_id()); + + child_api.TearDown(); + child_widget->CloseNow(); + child_widget.reset(); +} + +TEST_F(WidgetAXManagerTest, RemovingChildResetsParent) { + std::unique_ptr<Widget> child_widget = + base::WrapUnique(CreateChildNativeWidgetWithParent( + widget(), Widget::InitParams::CLIENT_OWNS_WIDGET)); + WidgetAXManagerTestApi child_api(child_widget->ax_manager()); + ASSERT_NE(child_api.parent_ax_tree_id(), ui::AXTreeID()); + + // Detach the child widget from its parent should reset the parent AXTreeID. + child_widget->Reparent(nullptr); + EXPECT_EQ(child_api.parent_ax_tree_id(), ui::AXTreeID()); + + child_api.TearDown(); + child_widget->CloseNow(); + child_widget.reset(); +} + class WidgetAXManagerOffTest : public ViewsTestBase { protected: WidgetAXManagerOffTest() {
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index c4babe9..e98d5787 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -842,6 +842,10 @@ void BubbleFrameView::SetBackgroundColor(ui::ColorVariant color) { bubble_border_->SetColor(color); + if (!GetWidget()) { + return; + } + UpdateClientViewBackground(); SchedulePaint(); }
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc index 442832f8..4bf95e8 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -13,6 +13,7 @@ #include "base/check_op.h" #include "base/command_line.h" #include "base/containers/flat_set.h" +#include "base/debug/dump_without_crashing.h" #include "base/functional/bind.h" #include "base/memory/ptr_util.h" #include "base/memory/scoped_refptr.h" @@ -191,7 +192,15 @@ display::win::GetScreenWin()->DIPToScreenRect(nullptr, params.bounds); message_handler_->Init(parent_hwnd, pixel_bounds); - UpdateWUCBackdrop(params.background_color); + if (ShouldAddDWMBackdrop()) { + DWM_SYSTEMBACKDROP_TYPE backdrop = DWMSBT_TRANSIENTWINDOW; + HRESULT hr = DwmSetWindowAttribute(GetHWND(), DWMWA_SYSTEMBACKDROP_TYPE, + &backdrop, sizeof(backdrop)); + CHECK_EQ(hr, S_OK); + } + + UpdateBackdropColorMode(); + CreateCompositor(params.force_software_compositing); OnAcceleratedWidgetAvailable(); InitHost(); @@ -229,7 +238,7 @@ void DesktopWindowTreeHostWin::OnWidgetThemeChanged( ui::ColorProviderKey::ColorMode color_mode, std::optional<SkColor> background_color) { - UpdateWUCBackdrop(background_color); + UpdateBackdropColorMode(); if (background_color) { ClearBackgroundPaintBrush(); background_paint_brush_ = @@ -1463,36 +1472,41 @@ allow_screenshots_ ? WDA_NONE : WDA_MONITOR); } -void DesktopWindowTreeHostWin::UpdateWUCBackdrop(std::optional<SkColor> color) { - // If the Redirection Surface is removed, there needs to be a replacement - // "background" of the Chromium window. Create a Windows.Ui.Composition - // backdrop and apply it to the window. If the frame is system drawn, it means - // that the window controls are rendered by Windows. In that case, they would - // be covered by the WUC backdrop, so only create the backdrop when frame mode - // is not `FrameMode::SYSTEM_DRAWN`. If the backdrop already exists, we need - // to check whether to keep it before updating it. - if (GetFrameMode() == FrameMode::SYSTEM_DRAWN) { - wuc_backdrop_.reset(); +void DesktopWindowTreeHostWin::UpdateBackdropColorMode() { + // Update backdrop theme using DWMWA_USE_IMMERSIVE_DARK_MODE. + if (!ShouldAddDWMBackdrop()) { return; } - if (GetWidget() && - ((message_handler_->window_ex_style() & WS_EX_NOREDIRECTIONBITMAP) == - WS_EX_NOREDIRECTIONBITMAP) && - !message_handler_->is_translucent()) { - // Ensure that the hwnd has been created. - CHECK(GetHWND()); - - // Apply backdrop to the window. - if (!wuc_backdrop_) { - wuc_backdrop_ = std::make_unique<gfx::WUCBackdrop>(GetHWND()); - } - - wuc_backdrop_->UpdateBackdropColor(color.value_or( - GetWidget()->GetColorProvider()->GetColor(ui::kColorFrameActive))); + // Ensure that the backdrop honors the OS dark mode setting. + BOOL use_dark_mode = + GetWidget()->GetColorMode() == ui::ColorProviderKey::ColorMode::kDark; + HRESULT hr = DwmSetWindowAttribute(GetHWND(), DWMWA_USE_IMMERSIVE_DARK_MODE, + &use_dark_mode, sizeof(use_dark_mode)); + if FAILED (hr) { + // TODO(crbug.com/415385215) DwmSetWindowAttribute can fail in certain + // scenarios. Create a dump so that these scenarios can be studied and + // prevented. + base::debug::Alias(&hr); + base::debug::DumpWithoutCrashing(); } } +bool DesktopWindowTreeHostWin::ShouldAddDWMBackdrop() { + // If the Redirection Surface is removed, there needs to be a replacement + // "background" of the Chromium window. `DWM_SYSTEMBACKDROP_TYPE` tells DWM + // to blur the contents behind the chromium window to yield a translucent + // "frosted glass" effect. This will show whenever the GPU crashes or is not + // ready by the time the window updates size or shape. Translucent windows + // do not need a backdrop as it would show up in unexpected ways - i.e. a + // gutter. Additionally, ensure that this effect is only applied to top level + // windows since child windows are not supported. + return ((message_handler_->window_ex_style() & WS_EX_NOREDIRECTIONBITMAP) == + WS_EX_NOREDIRECTIONBITMAP) && + !message_handler_->is_translucent() && + (GetHWND() == GetAncestor(GetHWND(), GA_ROOT)); +} + void DesktopWindowTreeHostWin::ClearBackgroundPaintBrush() { if (background_paint_brush_) { DeleteObject(background_paint_brush_);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h index a356654..0d567cbd 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -14,7 +14,6 @@ #include "ui/base/mojom/ui_base_types.mojom-shared.h" #include "ui/base/mojom/window_show_state.mojom-forward.h" #include "ui/display/display.h" -#include "ui/gfx/win/wuc_backdrop.h" #include "ui/views/views_export.h" #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h" #include "ui/views/win/hwnd_message_handler_delegate.h" @@ -297,11 +296,12 @@ // Call Windows API to update the window display affinity. void UpdateAllowScreenshots(); - // Creates a Windows.Ui.Composition backdrop and attaches it to the hwnd if - // the window does not have a redirection bitmap and Chromium is responsible - // for drawing the frame. Also resets the backdrop if the frame mode is - // changed to be system drawn. - void UpdateWUCBackdrop(std::optional<SkColor> color); + // Designates an acrylic DWM_SYSTEMBACKDROP to the window if it does not have + // a redirection bitmap. + void UpdateBackdropColorMode(); + + // Returns true if a DWM Backdrop should be applied to the window. + bool ShouldAddDWMBackdrop(); void ClearBackgroundPaintBrush(); @@ -348,9 +348,6 @@ // True if the window is allow to take screenshots, by default is true. bool allow_screenshots_ = true; - // A Windows.Ui.Composition visual tree that represents the window backdrop. - std::unique_ptr<gfx::WUCBackdrop> wuc_backdrop_; - // Visibility of the cursor. On Windows we can have multiple root windows and // the implementation of ::ShowCursor() is based on a counter, so making this // member static ensures that ::ShowCursor() is always called exactly once
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index 95d08ccc..31f18dc 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -2750,10 +2750,16 @@ } void Widget::OnChildAdded(Widget* child_widget) { + if (ax_manager_) { + ax_manager_->OnChildAdded(child_widget->ax_manager_.get()); + } observers_.Notify(&WidgetObserver::OnWidgetChildAdded, this, child_widget); } void Widget::OnChildRemoved(Widget* child_widget) { + if (ax_manager_) { + ax_manager_->OnChildRemoved(child_widget->ax_manager_.get()); + } observers_.Notify(&WidgetObserver::OnWidgetChildRemoved, this, child_widget); }
diff --git a/ui/views/window/default_frame_view.cc b/ui/views/window/default_frame_view.cc index 4f8eb2b..36dd3c22 100644 --- a/ui/views/window/default_frame_view.cc +++ b/ui/views/window/default_frame_view.cc
@@ -46,6 +46,9 @@ namespace { +// Various edges of the frame border have a 1 px shadow along their edges; +// in a few cases we shift elements based on this amount for visual appeal. +constexpr int kFrameShadowThickness = 1; // The frame border is only visible in restored mode and is hardcoded to 4 px on // each side regardless of the system window border size. constexpr int kFrameBorderThickness = 4; @@ -63,6 +66,9 @@ constexpr int kTitleIconOffsetX = 4; // The space between the title text and the caption buttons. constexpr int kTitleCaptionSpacing = 5; +// In restored mode, we draw a 1 px edge around the content area inside the +// frame border. +constexpr int kClientEdgeThickness = 1; void LayoutButton(ImageButton* button, const gfx::Rect& bounds) { button->SetVisible(true);
diff --git a/ui/views/window/non_client_view.h b/ui/views/window/non_client_view.h index 4d754ae..ee76c9d 100644 --- a/ui/views/window/non_client_view.h +++ b/ui/views/window/non_client_view.h
@@ -31,26 +31,11 @@ METADATA_HEADER(NonClientFrameView, View) public: - enum { - // Various edges of the frame border have a 1 px shadow along their edges; - // in a few cases we shift elements based on this amount for visual appeal. - kFrameShadowThickness = 1, - - // In restored mode, we draw a 1 px edge around the content area inside the - // frame border. - kClientEdgeThickness = 1, - }; - NonClientFrameView(); NonClientFrameView(const NonClientFrameView&) = delete; NonClientFrameView& operator=(const NonClientFrameView&) = delete; ~NonClientFrameView() override; - // Used to determine if the frame should be painted as active. Keyed off the - // window's actual active state and whether the widget should be rendered as - // active. - bool ShouldPaintAsActive() const; - // Helper for non-client view implementations to determine which area of the // window border the specified |point| falls within. The other parameters are // the size of the sizing edges, and whether or not the window can be @@ -112,15 +97,20 @@ // Whether the widget can be resized or maximized has changed. virtual void SizeConstraintsChanged() {} + // Inserts the passed client view into this NonClientFrameView. Subclasses can + // override this method to indicate a specific insertion spot for the client + // view. + virtual void InsertClientView(ClientView* client_view); + // View: void OnThemeChanged() override; void Layout(PassKey) override; Views GetChildrenInZOrder() override; - // Inserts the passed client view into this NonClientFrameView. Subclasses can - // override this method to indicate a specific insertion spot for the client - // view. - virtual void InsertClientView(ClientView* client_view); + protected: + // Used to determine if the frame should be painted as active. Convenience + // method; equivalent to GetWidget()->ShouldPaintAsActive(). + bool ShouldPaintAsActive() const; private: #if BUILDFLAG(IS_WIN)
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_compose_button.css b/ui/webui/resources/cr_components/searchbox/searchbox_compose_button.css index 5d43593..c6092ac 100644 --- a/ui/webui/resources/cr_components/searchbox/searchbox_compose_button.css +++ b/ui/webui/resources/cr_components/searchbox/searchbox_compose_button.css
@@ -20,7 +20,7 @@ font-size: inherit; border: none; position: relative; - gap: 2px; + gap: 3px; } .compose-container { @@ -33,6 +33,10 @@ .compose-icon { filter: invert(1); vertical-align: text-bottom; + height: 18px; + width: 18px; + padding-top: 2px; + padding-left: 1px; } #glowAnimationWrapper {
diff --git a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html.ts b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html.ts index 3adae60..56dfb10c 100644 --- a/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html.ts +++ b/ui/webui/resources/cr_elements/cr_checkbox/cr_checkbox.html.ts
@@ -15,7 +15,8 @@ </if> aria-disabled="${this.getAriaDisabled_()}" aria-checked="${this.getAriaChecked_()}" - aria-labelledby="labelContainer" + aria-label="${this.ariaLabelOverride || nothing}" + aria-labelledby="${this.ariaLabelOverride ? nothing : 'labelContainer'}" aria-describedby="ariaDescription"> <!-- Inline SVG paints faster than loading it from a separate file. --> <svg id="checkmark" width="12" height="12" viewBox="0 0 12 12" @@ -25,8 +26,7 @@ </svg> <div id="hover-layer"></div> </div> -<div id="labelContainer" aria-hidden="true" - aria-label="${this.ariaLabelOverride || nothing}" part="label-container"> +<div id="labelContainer" part="label-container"> <slot></slot> </div> <div id="ariaDescription" aria-hidden="true">${this.ariaDescription}</div>`;
diff --git a/v8 b/v8 index 68a0212..5110982 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 68a0212d298bc788debdbb225a168be96f63c7dd +Subproject commit 5110982b4020c8303ab7aece58818cb7eaee972e